Search documentation

Browse Awaken Agents docs
Docs/Awaken Agentsv1.0.0-dev/Developer guide/Connect an applicationAI SDK protocol
Note·You're reading pre-release documentation (v1.0.0-dev). Interfaces and behavior may change before a stable release.

Developer guide · Connect an application

AI SDK protocol

What this page covers

Connect a Vercel AI SDK UI to an Awaken Agent, then reconcile live output with committed Session history.

Use this protocol when the application already renders conversations with the Vercel AI SDK UIMessage model. Awaken accepts that request shape and returns an AI SDK v6 UI Message Stream, so the frontend can use its normal stream parser while Awaken continues to own Agent configuration and Session history.

Choose AG-UI instead when the application needs an AG-UI HttpAgent. Choose Managed Agents when an official Anthropic SDK should own the application contract. The connection matrix is the sole comparison of all protocol choices.

What crosses this boundary

flowchart LR
  UI[AI SDK UI<br/>UIMessage] -->|POST one turn or decision| Adapter[AI SDK adapter]
  Adapter --> App[RunApplication]
  App --> Ledger[Committed Session history]
  App -. best-effort Delta .-> Encoder[AiSdkEncoder]
  Ledger -->|committed Fact tail| Encoder
  Encoder -->|SSE UI Message Stream| UI

The adapter is a wire projection over the shared RunApplication. It does not define another Agent, tool registry, permission policy, or history store. AiSdkEncoder is the single stateful projection for both live Deltas and the committed Fact tail.

Send one turn

The default entry point is:

POST /v1/ai-sdk/chat
{
  "messages": [
    {
      "id": "msg-1",
      "role": "user",
      "parts": [{ "type": "text", "text": "Summarize the latest support request" }]
    }
  ],
  "threadId": "support-demo-1",
  "agentId": "support-agent"
}
FieldWhat to send
messagesAI SDK v6 UIMessage[]. New user and system text is input. Image file parts may use a hosted URL or a base64 Data URL. Other file media and UI-only parts are not model input.
threadIdReuse the same non-empty value for one conversation. Omit it only when the returned identifier does not need to be chosen by the application.
agentIdSelect one published Agent. Omit it to use the configured default.

Thread-scoped, Agent-scoped, and history routes are listed once in the Public HTTP API. The copy-ready React transport belongs in Integrate an AI SDK frontend.

Follow one request to completion

sequenceDiagram
  participant U as AI SDK UI
  participant A as AI SDK adapter
  participant R as RunApplication
  participant L as Session ledger

  U->>A: UIMessage[] + threadId
  A->>L: read committed message ids
  A->>A: discard replayed ids; decode new input or one tool decision
  alt new user or system input
    A->>R: run_streaming(thread, Agent, new messages)
    R-->>A: best-effort live Deltas
    A-->>U: start, text and tool-input SSE parts
  else matching tool result or approval
    A->>R: resume the awaiting tool call
  end
  R->>L: commit the Step outcome
  L-->>A: authoritative Fact tail and usage
  A-->>U: tool result or finish/error, then [DONE]

Each event is framed as an SSE data: line containing one JSON object. The response identifies the format with x-vercel-ai-ui-message-stream: v1, sends keep-alive comments while a turn is quiet, and ends with data: [DONE].

Live text and tool-argument deltas make the interface responsive. They are not the recovery record. The committed tail owns complete messages, tool availability and results, usage, awaiting state, and the terminal outcome. Read the thread history after reconnecting or when the application needs a durable view.

Interpret the stream

What the UI observesMeaningApplication action
text-start / text-delta / text-endOne displayable text block is being assembled.Render deltas in order. Treat the matching end as a block boundary, not as Session completion.
tool-input-* followed by tool-approval-requestA built-in tool is waiting for a permission decision.Return an AI SDK approval-responded part with the same toolCallId.
tool-input-available for a client-executed toolThe application owns tool execution.Return its output or error with the same toolCallId; this resumes the same awaiting call.
finish with tool-callsThe Run is waiting, not failed.Resolve the displayed tool or approval request. Do not start an unrelated turn.
finish with stopThe committed Step ended normally.The turn is complete. Read history when durable reconstruction matters.
error followed by finish with errorThe request or Run ended with a surfaced error.Show the error without treating partial live text as committed completion.

Reasoning lifecycle boundaries may be emitted, but private reasoning bytes are not sent. The adapter closes open text or reasoning blocks before changing to a tool block, so the UI does not need to repair block ordering.

Conditions the application must correct

Only errors that survive protocol handling and require a caller decision belong here:

Observable conditionCheckCorrective action
The stream contains error before useful outputValidate JSON, Content-Type, and the UIMessage field types. Decode failures are deliberately returned inside the stream rather than as plain-text HTTP errors.Correct the request and send it once.
A tool decision returns error saying no Run is awaiting, or names the wrong callCompare the submitted toolCallId with the current pending tool in committed history.Refresh history and submit a decision only for the current call. Do not reuse a decision from an older render.
error follows partial live outputRead committed history for the same threadId before deciding whether more work is needed.Preserve the error text and current ids. Do not resend the same input merely because the browser displayed only a prefix.

A browser disconnect is not a manual recovery task. The adapter interrupts the in-flight Run automatically so it does not continue detached. Reopen the thread from committed history; do not invent a reconnect, cancel, or draft-preview URL under /v1/ai-sdk.