Polpo exposes an OpenAI-compatible chat completions endpoint. You can talk to any agent using the same format as the OpenAI API — streaming or non-streaming.
How it works
- You send a message to a specific agent via
POST /v1/chat/completions
- The agent receives your message along with its system prompt, skills, identity, and memory
- The agent responds using its configured model and tools
- Conversation history is stored in a session for multi-turn chat
Streaming
curl -X POST https://{project}.polpo.cloud/v1/chat/completions \
-H "Authorization: Bearer $POLPO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent": "backend-dev",
"messages": [
{ "role": "user", "content": "Explain how the auth module works" }
],
"stream": true
}'
The response is a standard SSE stream of OpenAI-compatible chunks:
data: {"choices":[{"delta":{"role":"assistant","content":"The auth"},"index":0}]}
data: {"choices":[{"delta":{"content":" module uses"},"index":0}]}
data: {"choices":[{"delta":{"content":" JWT tokens..."},"index":0}]}
data: [DONE]
Non-streaming
curl -X POST https://{project}.polpo.cloud/v1/chat/completions \
-H "Authorization: Bearer $POLPO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent": "backend-dev",
"messages": [
{ "role": "user", "content": "Explain how the auth module works" }
],
"stream": false
}'
Sessions
Each conversation is tracked as a session. The response includes a x-session-id header containing the session ID.
Without an x-session-id request header, a new session is always created. To continue an existing conversation, pass the session ID explicitly:
# First message — creates a new session
curl -X POST https://{project}.polpo.cloud/v1/chat/completions \
-H "Authorization: Bearer $POLPO_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "agent": "dev", "messages": [{ "role": "user", "content": "Hello" }] }'
# Response header: x-session-id: sess_abc123
# Continue the conversation — pass the session ID
curl -X POST https://{project}.polpo.cloud/v1/chat/completions \
-H "Authorization: Bearer $POLPO_API_KEY" \
-H "x-session-id: sess_abc123" \
-H "Content-Type: application/json" \
-d '{ "agent": "dev", "messages": [{ "role": "user", "content": "Follow up" }] }'
# Force a new session even when a header is present
curl -X POST https://{project}.polpo.cloud/v1/chat/completions \
-H "Authorization: Bearer $POLPO_API_KEY" \
-H "x-session-id: new" \
-H "Content-Type: application/json" \
-d '{ "agent": "dev", "messages": [{ "role": "user", "content": "Fresh start" }] }'
There is no automatic session reuse. If you omit x-session-id, every request starts a new conversation. Your client is responsible for storing and passing the session ID.
SDK usage
Streaming
import { PolpoClient } from "@polpo-ai/sdk";
const client = new PolpoClient({
baseUrl: "https://{project}.polpo.cloud",
apiKey: "sk_live_...",
});
const stream = client.chatCompletionsStream({
agent: "backend-dev",
messages: [{ role: "user", content: "Refactor the payment module" }],
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
console.log("\nSession:", stream.sessionId);
Aborting
const stream = client.chatCompletionsStream({ agent: "dev", messages });
setTimeout(() => stream.abort(), 10_000); // cancel after 10s
Non-streaming
const response = await client.chatCompletions({
agent: "backend-dev",
messages: [{ role: "user", content: "Explain the auth flow" }],
});
console.log(response.choices[0].message.content);
What the agent receives
When you send a chat completion, the agent’s full context includes:
- System prompt — base Polpo prompt + agent’s
systemPrompt field
- Identity — display name, title, tone, personality, responsibilities
- Skills — domain knowledge from assigned skills
- Memory — shared + agent-specific memory
- Tools — all tools from
allowedTools
- Your messages — the conversation history
File attachments
To attach a file to a conversation, upload it to the workspace and reference it in your message.
1. Upload the file
curl -X POST https://{project}.polpo.cloud/api/v1/files/upload \
-H "Authorization: Bearer $POLPO_API_KEY" \
-F "file=@report.pdf" \
-F "path=workspace"
2. Reference it in the message
Pass a file content part with the workspace path as file_id:
curl -X POST https://{project}.polpo.cloud/v1/chat/completions \
-H "Authorization: Bearer $POLPO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent": "coder",
"messages": [{
"role": "user",
"content": [
{ "type": "text", "text": "Analyze this report" },
{ "type": "file", "file_id": "workspace/report.pdf" }
]
}],
"stream": true
}'
The agent receives a reference to the file and uses its built-in tools to access the content. Images are analyzed visually, text files are read directly.
Files live in the workspace filesystem and persist across messages in the same session.
Agents can use tools during the conversation (read files, run commands, fetch URLs, etc.). Most tool calls happen server-side — the agent executes them automatically and you receive the final response.
Some tools require interaction with the user. These are client-side tools — the agent calls them, but instead of executing on the server, the tool call is returned to your client for handling.
The built-in client-side tool is ask_user_question. When the agent needs clarification, it calls this tool with structured questions and options. Your client renders the questions, collects the user’s response, and sends it back.
The flow:
- Agent calls
ask_user_question — server returns finish_reason: "ask_user" with the questions
- Your client shows the question UI
- User responds
- Client sends the answer as a tool result message in the next request
- Agent continues with the answer
# Step 1: Agent responds with a tool call
# Response chunk:
{
"choices": [{
"delta": {
"tool_calls": [{
"id": "call_abc123",
"type": "function",
"function": {
"name": "ask_user_question",
"arguments": "{\"questions\":[{\"id\":\"deploy-target\",\"question\":\"Where should I deploy?\",\"options\":[{\"label\":\"Staging\"},{\"label\":\"Production\"}]}]}"
}
}]
},
"finish_reason": "ask_user"
}]
}
# Step 4: Send the answer back
curl -X POST https://{project}.polpo.cloud/v1/chat/completions \
-H "Authorization: Bearer $POLPO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent": "coder",
"messages": [
{"role": "user", "content": "Deploy the app"},
{"role": "tool", "tool_call_id": "call_abc123", "name": "ask_user_question", "content": "{\"answers\":[{\"questionId\":\"deploy-target\",\"selected\":[\"Staging\"]}]}"}
],
"stream": true
}'
The completions API is fully compatible with OpenAI client libraries. You can use the official openai Python/Node.js package by pointing it at your Polpo endpoint.