agui://¶
Expose a Helix agent to a frontend via the CopilotKit AG-UI (Agent-User Interaction) protocol. The consumer stands up an HTTP POST endpoint that accepts a JSON RunAgentInput, runs the agent through the route's pipeline, and streams TEXT_MESSAGE_* events back as Server-Sent Events. Use agui:// when you want a chat-style streaming endpoint that drops into CopilotKit / Vercel AI SDK / any AG-UI-compatible client.
For richer declarative UI (cards, columns, forms), see a2ui://. For the more powerful peer-to-peer protocol, see a2a-server://.
Consumer-only — CreateProducer returns an error.
URI shape¶
<host:port>— listen address. If port is missing,4100is used.<path>— HTTP path (default/).
Parameters¶
| Param | Type | Default | Producer/Consumer/Both | Description |
|---|---|---|---|---|
(path) host |
string | — | Consumer | Host:port to listen on. |
(path) path |
string | / |
Consumer | HTTP path. |
name |
string | helix-agui |
Consumer | Server identity (informational). |
native |
boolean | false |
Consumer | When true, the route's own processor pipeline handles the request directly. When false (discovery mode), the server scans every direct:// / seda:// workflow and routes calls to the first one found. |
corsOrigin |
string | * |
Consumer | Access-Control-Allow-Origin value. Set to a specific origin in production. |
HTTP surface¶
POST <path>¶
Body: AG-UI RunAgentInput JSON. The server:
- Extracts the last user message (text + any multimodal parts: images, audio, files).
- If only attachments are present (no text), auto-generates a prompt based on the dominant content type ("Analyze this image and describe what you see.", etc.).
- For non-image binary files (PDF, CSV, JSON, YAML, plain text, ...), inlines the content as text:
- text/* and JSON/XML/YAML → embedded verbatim.
- PDFs → built-in text extraction; falls back to OCR (configurable via
helix.ocr.{backend,endpoint,api_key}config /HELIX_OCR_*env, default backenddoclingonhttp://localhost:5001). Output is truncated to 100 K chars to fit LLM context. - other binaries → stub text noting the upload.
- Materializes an exchange and runs it through the pipeline (or, in discovery mode, hands it to the first invocable producer).
- Streams responses back as AG-UI events.
Request bodies are capped at 10 MB. CORS preflight (OPTIONS) is supported.
Event flow¶
For every request the server emits:
RUN_STARTED { threadID, runID }
TEXT_MESSAGE_START { messageID, role: "assistant" }
TEXT_MESSAGE_CONTENT { messageID, delta }
...
TEXT_MESSAGE_END { messageID }
RUN_FINISHED { threadID, runID }
threadID is taken from the input (or generated). The same threadID is used as the session key when a session store is configured.
Per-call exchange shape¶
| Header | Description |
|---|---|
HelixStream |
"true" — downstream producers use streaming. |
HelixAGUIThreadID |
The AG-UI thread (== session id when session store is on). |
HelixAGUIRunID |
The AG-UI run id. |
HelixAGUIState |
JSON of the input's state field (if any). |
HelixAGUITools |
JSON of the input's tools field (if any). |
Body: the user text, or — when files / images / audio are attached — a multipart body (exchange.SetMultipartBody). The pipeline can return:
| Body type | Effect |
|---|---|
*llm.StreamReader |
Each non-empty chunk becomes a TEXT_MESSAGE_CONTENT event. |
chan string / <-chan string |
Same — driven by channel. |
| anything else | The full body as one TEXT_MESSAGE_CONTENT event. |
After the stream finishes, the assembled assistant text is appended to the session's conversation history, and a helix.response.content exchange property is set for tracer / audit downstream.
Examples¶
Single-agent chat endpoint for CopilotKit:
agents:
- id: helper
type: react
model: { provider: openai, model: gpt-4o }
system-prompt: "You are a helpful assistant."
workflows:
- id: chat
trigger:
uri: agui://0.0.0.0:4100/?corsOrigin=https://app.example.com
steps:
- target: agent://helper
CopilotKit config (frontend):
import { CopilotKit } from "@copilotkit/react-core";
<CopilotKit runtimeUrl="http://helix.local:4100/">
<ChatUI />
</CopilotKit>
Multiple workflows on different paths:
workflows:
- id: agui-research
trigger: { uri: agui://0.0.0.0:4100/research?native=true }
steps:
- target: agent://researcher
- id: agui-translate
trigger: { uri: agui://0.0.0.0:4100/translate?native=true }
steps:
- target: agent://translator
(With native=true the route's own pipeline handles the request — no auto-discovery scan; one AG-UI server per workflow.)
Discovery mode — point at an existing direct:// workflow:
workflows:
- id: ask
trigger: { uri: direct://ask }
steps:
- target: agent://helper
- id: agui-server
trigger: { uri: agui://0.0.0.0:4100/ } # discovers the 'ask' route
steps: []
Behavior notes¶
- Two modes — discovery (default) scans
direct:///seda://workflows; native (native=true) uses the route's own pipeline. Discovery is convenient when a single AG-UI server fronts many internal workflows; native gives you per-endpoint configuration. - PDF handling — when a PDF is uploaded, the server tries
pkg/rag/ingest.NewPDFReaderfirst (fast text extraction). If that returns < 50 chars, OCR fallback runs. Embedded base64 image data URIs are stripped from the OCR output (sanitizePDFContent) to keep context windows sane. - Truncation — extracted document text is capped at 100 000 chars before reaching the LLM.
- Session history — when a session store is configured, the user's prompt and the streamed assistant response are appended to
sess.ConversationHistory. - CORS exposure —
Content-TypeandX-Helix-Sessionare listed inAccess-Control-Expose-Headersso the frontend can read them.
Source¶
pkg/component/agui/server.go
See also¶
- a2ui — rich declarative UI alternative.
- a2a-server, mcp-server — peer-protocol servers.
- agent — the underlying agent runtime.
- RAG ingest reference — the PDF / OCR readers reused here.