> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polpo.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Chat Completions

> Talk to agents through the OpenAI-compatible completions endpoint

Send OpenAI-style messages to `POST /v1/chat/completions`. Set `agent` for direct agent mode; omit it to use the project orchestrator. `model` can override the selected agent model for a single call. `temperature`, `max_tokens`, and the deprecated `project` field are accepted for compatibility and applied when supported by the runtime/provider path.

An optional `loop` selects one of the target agent's `assignedLoops`.

## Request

```bash theme={null}
curl -N "https://{project-slug}.polpo.cloud/v1/chat/completions" \
  -H "Authorization: Bearer $POLPO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent": "backend-dev",
    "loop": "qa-flow",
    "model": "anthropic/claude-sonnet-4-5",
    "sandbox": {"isolation": "reuse"},
    "messages": [
      {"role": "user", "content": "Explain the authentication flow"}
    ],
    "stream": true
  }'
```

Streaming uses server-sent events and ends with `data: [DONE]`. Set `stream: false` for one `chat.completion` JSON response.

Messages support `system`, `user`, `assistant`, and `tool` roles. Content can be a string or an array of `text`, `image_url`, and `file` parts. `user` is an opaque caller-provided end-user identifier; Polpo does not authenticate it. `sandbox.isolation` can be `reuse` or `fresh` for the current run. `metadata` accepts up to 16 string entries, with keys up to 64 characters and values up to 512 characters.

## Sessions

Every response includes `x-session-id`. If the request has no `x-session-id` header, Polpo creates a new session. Persist the returned value and send it on later requests:

```bash theme={null}
curl "https://{project-slug}.polpo.cloud/v1/chat/completions" \
  -H "Authorization: Bearer $POLPO_API_KEY" \
  -H "x-session-id: sess_abc123" \
  -H "Content-Type: application/json" \
  -d '{
    "agent": "backend-dev",
    "messages": [{"role": "user", "content": "Continue"}]
  }'
```

Use `x-session-id: new` to force a new session. There is no implicit reuse when the header is omitted.

## TypeScript SDK

```typescript theme={null}
import { PolpoClient } from "@polpo-ai/sdk";

const client = new PolpoClient({
  baseUrl: "https://{project-slug}.polpo.cloud",
  apiKey: process.env.POLPO_API_KEY!,
});

const stream = client.chatCompletionsStream({
  agent: "backend-dev",
  messages: [{ role: "user", content: "Review the auth module" }],
});

for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}

console.log(stream.sessionId);
```

Pass `sessionId` in the SDK request to continue a session. Call `stream.abort()` to cancel a streaming request.

## Files and images

Upload a file to an existing workspace directory through the public Files API:

```bash theme={null}
curl -X POST "https://{project-slug}.polpo.cloud/v1/files/upload" \
  -H "Authorization: Bearer $POLPO_API_KEY" \
  -F "path=workspace" \
  -F "file=@report.pdf"
```

Then use the workspace-relative path as `file_id`:

```json theme={null}
{
  "role": "user",
  "content": [
    {"type": "text", "text": "Read and summarize this report"},
    {"type": "file", "file_id": "report.pdf"}
  ]
}
```

A `file` part becomes a text reference to a workspace-relative path, so the agent needs suitable file tools to inspect it. For direct multimodal image input, use an `image_url` part with an HTTPS URL or data URL and configure a compatible vision model. Workspace files persist at project scope, not session scope.

## Client-side tool calls

Interactive tools such as `ask_user_question` stop the server loop and return `finish_reason: "ask_user"`. To resume, continue the same `x-session-id` and send a `tool` message with the returned `tool_call_id`, tool `name`, and serialized answer in `content`. The interrupted assistant tool call is already stored in that session.

The endpoint follows OpenAI chat request and response conventions, but `agent`, `loop`, session headers, and Polpo finish reasons are extensions. OpenAI clients may require an extra-body mechanism for those fields.
