Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 26 additions & 5 deletions services/global_chat/PAYLOAD_SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,13 @@ This document defines the input and output payload structure for the Global Agen

```json
{
"response": "string", // Main text response
"response": "string", // Main text response (final answer)

"response_segments": [ // Durable transcript of the turn, in stream order
{ "type": "text", "content": "I'll add the step..." },
{ "type": "status", "content": "Edited workflow structure" },
{ "type": "text", "content": "Done! I added..." }
],

"attachments": [ // Artifacts produced this turn
{
Expand All @@ -96,8 +102,8 @@ This document defines the input and output payload structure for the Global Agen
"history": [ // Conversation history including this turn
{
"role": "user|assistant",
"content": "string | array" // string for direct routes; array of content
} // blocks (text, tool_use, tool_result) for planner path
"content": "string"
}
],

"usage": { // Token usage (aggregated across all agents)
Expand Down Expand Up @@ -125,11 +131,26 @@ This document defines the input and output payload structure for the Global Agen

### Field Descriptions

- **`response`** (string): The main text response from the agent.
- **`response`** (string): The main text response from the agent — the final answer. On the planner path this is the text of the planner's last round only (narration from earlier rounds is not included).

- **`response_segments`** (array): The durable transcript of the turn in the order it was streamed, as `{"type", "content"}` objects. Two segment types:
- `text` — a text block from the model. On the planner path there is one per round of the tool-calling loop; the last one equals `response`.
- `status` — a completed-action status line ("Edited workflow structure", "Wrote code for \"Fetch Patients\""). Only these settled lines are recorded; the transient "...ing" spinners shown while an action runs are never persisted.

This lets the frontend persist and re-render the woven view after a page reload without reconstructing it from stream events. On direct routes (workflow_agent, job_code_agent) it is a single `text` segment wrapping `response` — statuses emitted internally by those subagents are not captured.

#### Streaming status events (planner path)

Apollo classifies status messages by event type so the client never has to infer their meaning from the text:

- **`thinking` events** (standard Anthropic thinking blocks) — transient progress spinners ("Reviewing the workflow...", "Writing code for \"X\"..."). Render live; each new status replaces the previous one; drop when the next text block starts. Never persist these.
- **`status` events** (custom event, like `changes`) — completed-action lines. Payload is `{"type": "status", "content": "Edited workflow structure"}`, identical to a `response_segments` entry, so live events and reloaded segments render through the same code path. Persist these (they resolve the preceding spinner).

Each tool beat streams as: `thinking` spinner → `changes` (if the workflow was modified) → `status` settled line → narration text.

- **`attachments`** (array): Artifacts produced during this turn. Each entry has a `type` and `content` field. An empty list `[]` means no artifacts were produced (e.g. a purely informational response). The only supported type is `workflow_yaml`: the full workflow YAML with any job code changes stitched in. Job code edits are never returned separately — the YAML is the single source of truth, which allows multi-step changes in one response.

- **`history`** (array): Updated conversation history including the latest exchange. On direct routes (workflow_agent, job_code_agent), each entry has `content` as a string. On the planner path, entries may have `content` as an array of content blocks (`text`, `tool_use`, `tool_result`) — this is the raw Anthropic messages format from the tool-calling loop.
- **`history`** (array): Updated conversation history including the latest exchange. Each entry has `content` as a string on every route. On the planner path the assistant entry contains only the final answer text — the pre-tool narration segments in `response` are not persisted to history.

- **`usage`** (object): Token usage aggregated across all agents invoked (router + planner + sub-agents).

Expand Down
1 change: 1 addition & 0 deletions services/global_chat/global_chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ def main(data_dict: dict) -> dict:
# 5. Return structured response
return {
"response": result.response,
"response_segments": result.response_segments,
"attachments": result.attachments,
"history": result.history,
"usage": result.usage,
Expand Down
Loading