AI agent state hooks (useKoderAgent / useKoderChat)
patterns specs/patterns/ai-agent-state-hooks.kmd
Framework-neutral state-machine contract for any AI chat / agent surface in a Koder product — message list, streaming state, append handlers, abort, retry, tool-call lifecycle. Companion to patterns/ai-chat-surface.kmd (which ratifies the 6 primitives); this spec ratifies the state machine driving them. Modeled after Ant Design X `useXAgent` / `useXChat`.
Quando este padrão se aplica
Triggers primários
- Implement the state layer behind any AI chat surface in a Koder product
Todos os triggers
- Wire an AI chat surface to a transport / model
- Author a state-machine for an AI agent UI
Corpo da especificação
Pattern — AI agent state hooks
Status: v0.1.0 — Draft. Contract-only; per-framework implementations (
useKoderAgentfor React,KoderAgentControllerfor Flutter,KoderAgentViewModelfor Kotlin / Swift) live in the respective SDK backlogs.
R1 — Three roles, one machine
The state machine has three logical roles a consumer may attach to:
| Role | Responsibility |
|---|---|
| Agent | Owns the transport: opens connection, streams tokens, surfaces lifecycle events. |
| Chat | Owns the message list: append user message, append assistant streaming, mutate history, dispatch retry. |
| Tool host | Owns tool-call lifecycle (when AI emits a tool call): present permission prompt, dispatch tool, append tool-result to history. |
A simple chat-only surface attaches Chat alone. An agent-heavy surface (Kortex assist with tool use) attaches all three.
R2 — Required state shape
Every framework binding MUST expose at least:
| Field | Type | Notes |
|---|---|---|
messages | Message[] | Ordered history (user / assistant / system / tool) |
streaming | boolean | True between requestSend and streamEnd / error |
lastError | Error | null | Most recent transport / model error (cleared on requestSend) |
abortable | boolean | True iff a stream can be aborted now |
pendingToolCalls | ToolCall[] | Tool calls awaiting user permission per specs/ai-ui/permission-prompt.kmd |
R3 — Required actions
| Action | Effect |
|---|---|
send(text, attachments?) | Append user message → start stream |
regenerate(messageId) | Re-run from the prior turn; discards subsequent history |
edit(messageId, newText) | Mutate user message → regenerate from that turn |
branch(messageId) | Fork: create a new conversation from this turn (per specs/ai-ui/conversation-history.kmd) |
abort() | Cancel in-flight stream; partial response retained in history with aborted: true |
clear() | Reset to empty (does NOT delete conversation in storage; that's a separate delete() for explicit removal) |
R4 — Lifecycle events (emitted to subscribers)
onUserMessage → onStreamStart → onStreamToken (many) → onToolCall (optional) → onStreamEnd | onError | onAbort
Consumers MAY hook any subset. The state shape (R2) is the canonical view; events are for side effects (telemetry, sound, haptics).
R5 — Tool-call lifecycle (subset)
When AI emits a tool call:
pendingToolCallsgets the entry,streaming: false.- Consumer surfaces
permission-prompt.kmdUI. - On approve: framework binding dispatches to the registered tool;
on result,
messagesgains atoolentry;streaming: trueresumes. - On deny: append
toolentry withdenied: true;streaming: trueresumes (AI sees denial in context).
R6 — Multi-conversation
The hook is scoped per-conversation. Switching conversations (per
specs/ai-ui/conversation-history.kmd) instantiates a new hook with
its own state. Consumers maintain a list of hook instances or use a
provider that supplies the active one.
R7 — Concurrency
- Only one
sendcan be in flight per hook instance. - A second
sendwhilestreaming: trueis rejected with a clear error; consumers should disable the Sender button (#066Sender primitive R3 morphs to Stop).
R8 — i18n + a11y
State is locale-neutral; user-facing strings come from patterns/ ai-chat-surface.kmd + patterns/ai-feature-visual-language.kmd
disclosure microcopy. Hooks MUST surface streaming state in a form
the Bubble primitive can route to aria-live="polite".
Não-escopo
- Transport protocol (SSE / WebSocket / chunked HTTP) — separate
specs/ai-ui/transport.kmdif pursued. - Token counting / cost display — covered by
specs/ai-ui/cost-display.kmd. - Memory / RAG retrieval — separate spec.
Referências
specs/patterns/ai-chat-surface.kmdspecs/patterns/ai-feature-visual-language.kmdspecs/ai-ui/agent-step-trace.kmd