Skip to content

feat: add docker agent serve chat command (OpenAI-compatible API)#2510

Draft
dgageot wants to merge 1 commit intodocker:mainfrom
dgageot:board/add-docker-agent-serve-chat-command-0b138539
Draft

feat: add docker agent serve chat command (OpenAI-compatible API)#2510
dgageot wants to merge 1 commit intodocker:mainfrom
dgageot:board/add-docker-agent-serve-chat-command-0b138539

Conversation

@dgageot
Copy link
Copy Markdown
Member

@dgageot dgageot commented Apr 25, 2026

Fixes #2502.

Exposes any docker-agent agent through an OpenAI-compatible HTTP server, so any tool that already speaks the Chat Completions protocol (Open WebUI, the official openai SDKs, ad-hoc curl scripts, etc.) can drive an agent without a custom integration.

Endpoints

Method Path Notes
GET /v1/models Lists exposed agents as OpenAI models
POST /v1/chat/completions Runs the agent; supports stream: true (SSE) and false

Usage

docker agent serve chat ./agent.yaml                       # localhost:8083
docker agent serve chat ./team.yaml --agent reviewer       # pin one agent
docker agent serve chat agentcatalog/pirate --listen :9090
curl -sS -X POST http://127.0.0.1:8083/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{"messages":[{"role":"user","content":"hi"}]}'

Design

  • The team is loaded once at startup and shared across requests. Each chat completion gets a fresh session and runtime.
  • The session is created with ToolsApproved=true and NonInteractive=true — there is no human in the loop. ElicitationRequestEvent is still explicitly declined to avoid hanging on the runtime's elicitation channel.
  • The model field of the request can pin a specific agent in a multi-agent team. If it doesn't match an exposed agent (e.g. clients that hard-code gpt-4) we silently fall back to the default agent and echo the requested model name back, so clients matching on the model field stay happy.
  • Streaming uses SSE in OpenAI's chat.completion.chunk format and ends with data: [DONE].

Implementation

  • New cobra command cmd/root/chat.go (default 127.0.0.1:8083, --agent / --listen flags) wired into cmd/root/serve.go.
  • New pkg/chatserver package, split across:
    • server.goRun, router, HTTP handlers, sseStream, error envelope
    • agent.goagentPolicy, buildSession, runAgentLoop, sessionUsage
    • types.go — request/response shapes
  • Reuses openai.Model from github.com/openai/openai-go/v3 for /v1/models. Other SDK response types serialise too noisily with stdlib encoding/json (the SDK relies on its internal apijson package, which lives under internal/), so the chat-completion shapes are hand-rolled for clean output.

Tests

  • Unit tests for session-building, agent-policy resolution, usage extraction.
  • HTTP-level tests via httptest for /v1/models shape, the three early-validation paths of /v1/chat/completions (bad JSON, empty messages, history without user), and writeError's status→type mapping.

Validation

  • mise lint — 0 issues
  • mise test — all packages green
  • Manual curl smoke test against examples/42.yaml: /v1/models returns the agent, error paths return correct OpenAI-shaped envelopes.

@dgageot dgageot requested a review from a team as a code owner April 25, 2026 18:00
Expose any docker-agent agent through an OpenAI-compatible HTTP
server, so tools that already speak the Chat Completions protocol
(Open WebUI, the official `openai` SDKs, ad-hoc curl scripts, etc.)
can drive an agent without any custom integration.

Endpoints:
  GET  /v1/models             — lists exposed agents as OpenAI models
  POST /v1/chat/completions   — runs the agent; supports stream: true
                                (Server-Sent Events) and false

The team is loaded once at startup and shared across requests; each
chat completion gets a fresh session and runtime. Tool calls and
elicitation prompts are auto-handled (this is a non-interactive
endpoint). The `model` field can pin a specific agent in a multi-
agent team, or is ignored and the team's default agent runs.

Implementation notes:

- New `cmd/root/chat.go` cobra command (default 127.0.0.1:8083,
  --agent / --listen flags) wired into `cmd/root/serve.go`.
- New `pkg/chatserver` package, split into:
  - server.go — Run, router, HTTP handlers, sseStream, errors
  - agent.go  — agentPolicy, buildSession, runAgentLoop, sessionUsage
  - types.go  — request/response shapes
- Reuses `openai.Model` from github.com/openai/openai-go/v3 for
  /v1/models. Other OpenAI SDK response types serialise too noisily
  with stdlib `encoding/json` (the SDK relies on its internal
  `apijson` package which we can't import), so request/response
  shapes are hand-rolled for clean output.
- Defensive event handling in runAgentLoop: ToolsApproved=true and
  NonInteractive=true mean the runtime never blocks for confirmation
  in normal flow, but ElicitationRequestEvent must still be answered
  or the runtime would hang on its dedicated channel.

Tests cover session-building, agent-policy, error-envelope shape,
and the three early-validation paths of /v1/chat/completions via
httptest. Validated with `mise lint` (0 issues), `mise test` (all
packages green), and a curl smoke test against examples/42.yaml.

Fixes docker#2502

Assisted-By: docker-agent
@dgageot dgageot force-pushed the board/add-docker-agent-serve-chat-command-0b138539 branch from 40d4ebc to 8711dac Compare April 25, 2026 20:25
@dgageot dgageot marked this pull request as draft April 26, 2026 10:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support for OpenAI-compatible API server

2 participants