|
| 1 | +# Universal ↔ Agent Term Mapping |
| 2 | + |
| 3 | +Source of truth: generated agent schemas in `resources/agent-schemas/artifacts/json-schema/`. |
| 4 | + |
| 5 | +Identifiers |
| 6 | + |
| 7 | ++----------------------+------------------------+------------------------------------------+-----------------------------+------------------------+ |
| 8 | +| Universal term | Claude | Codex (app-server) | OpenCode | Amp | |
| 9 | ++----------------------+------------------------+------------------------------------------+-----------------------------+------------------------+ |
| 10 | +| session_id | n/a (daemon-only) | n/a (daemon-only) | n/a (daemon-only) | n/a (daemon-only) | |
| 11 | +| native_session_id | none | threadId | sessionID | none | |
| 12 | +| item_id | synthetic | ThreadItem.id | Message.id | StreamJSONMessage.id | |
| 13 | +| native_item_id | none | ThreadItem.id | Message.id | StreamJSONMessage.id | |
| 14 | ++----------------------+------------------------+------------------------------------------+-----------------------------+------------------------+ |
| 15 | + |
| 16 | +Notes: |
| 17 | +- When a provider does not supply IDs (Claude), we synthesize item_id values and keep native_item_id null. |
| 18 | +- native_session_id is the only provider session identifier. It is intentionally used for thread/session/run ids. |
| 19 | +- native_item_id preserves the agent-native item/message id when present. |
| 20 | + |
| 21 | +Events / Message Flow |
| 22 | + |
| 23 | ++------------------------+------------------------------+--------------------------------------------+-----------------------------------------+----------------------------------+ |
| 24 | +| Universal term | Claude | Codex (app-server) | OpenCode | Amp | |
| 25 | ++------------------------+------------------------------+--------------------------------------------+-----------------------------------------+----------------------------------+ |
| 26 | +| session.started | none | method=thread/started | type=session.created | none | |
| 27 | +| session.ended | SDKMessage.type=result | no explicit session end (turn/completed) | no explicit session end (session.deleted)| type=done | |
| 28 | +| message (user) | SDKMessage.type=user | item/completed (ThreadItem.type=userMessage)| message.updated (Message.role=user) | type=message | |
| 29 | +| message (assistant) | SDKMessage.type=assistant | item/completed (ThreadItem.type=agentMessage)| message.updated (Message.role=assistant)| type=message | |
| 30 | +| message.delta | synthetic | method=item/agentMessage/delta | type=message.part.updated (delta) | synthetic | |
| 31 | +| tool call | synthetic from tool usage | method=item/mcpToolCall/progress | message.part.updated (part.type=tool) | type=tool_call | |
| 32 | +| tool result | synthetic from tool usage | item/completed (tool result ThreadItem variants) | message.part.updated (part.type=tool, state=completed) | type=tool_result | |
| 33 | +| permission.requested | none | none | type=permission.asked | none | |
| 34 | +| permission.resolved | none | none | type=permission.replied | none | |
| 35 | +| question.requested | ExitPlanMode tool (synthetic)| experimental request_user_input (payload) | type=question.asked | none | |
| 36 | +| question.resolved | ExitPlanMode reply (synthetic)| experimental request_user_input (payload) | type=question.replied / question.rejected | none | |
| 37 | +| error | SDKResultMessage.error | method=error | type=session.error (or message error) | type=error | |
| 38 | ++------------------------+------------------------------+--------------------------------------------+-----------------------------------------+----------------------------------+ |
| 39 | + |
| 40 | +Synthetics |
| 41 | + |
| 42 | ++------------------------------+------------------------+--------------------------+--------------------------------------------------------------+ |
| 43 | +| Synthetic element | When it appears | Stored as | Notes | |
| 44 | ++------------------------------+------------------------+--------------------------+--------------------------------------------------------------+ |
| 45 | +| session.started | When agent emits no explicit start | session.started event | Mark origin=daemon | |
| 46 | +| session.ended | When agent emits no explicit end | session.ended event | Mark origin=daemon; reason may be inferred | |
| 47 | +| item_id (Claude) | Claude provides no item IDs | item_id | Maintain provider_item_id map when possible | |
| 48 | +| user message (Claude) | Claude emits only assistant output | item.completed | Mark origin=daemon; preserve raw input in event metadata | |
| 49 | +| question events (Claude) | Plan mode ExitPlanMode tool usage | question.requested/resolved | Synthetic mapping from tool call/result | |
| 50 | +| native_session_id (Codex) | Codex uses threadId | native_session_id | Intentionally merged threadId into native_session_id | |
| 51 | ++------------------------------+------------------------+--------------------------+--------------------------------------------------------------+ |
| 52 | +| message.delta (Claude/Amp) | No native deltas | item.delta | Synthetic delta with full message content; origin=daemon | |
| 53 | ++------------------------------+------------------------+--------------------------+--------------------------------------------------------------+ |
| 54 | +| message.delta (OpenCode) | part delta before message | item.delta | If part arrives first, create item.started stub then delta | |
| 55 | ++------------------------------+------------------------+--------------------------+--------------------------------------------------------------+ |
| 56 | + |
| 57 | +Delta handling |
| 58 | + |
| 59 | +- Codex emits agent message and other deltas (e.g., item/agentMessage/delta). |
| 60 | +- OpenCode emits part deltas via message.part.updated with a delta string. |
| 61 | +- Claude and Amp do not emit deltas in their schemas. |
| 62 | + |
| 63 | +Policy: |
| 64 | +- Always emit item.delta across all providers. |
| 65 | +- For providers without native deltas, emit a single synthetic delta containing the full content prior to item.completed. |
| 66 | +- For providers with native deltas, forward as-is; also emit item.completed when final content is known. |
| 67 | + |
| 68 | +Message normalization notes |
| 69 | + |
| 70 | +- user vs assistant: normalized via role in the universal item; provider role fields or item types determine role. |
| 71 | +- OpenCode unrolling: message.updated creates/updates the parent message item; tool-related parts emit separate tool item events (item.started/ item.completed) with parent_id pointing to the message item. |
| 72 | +- If a message.part.updated arrives before message.updated, we create a stub item.started (origin=daemon) so deltas have a parent. |
0 commit comments