Streaming

Sending a message and observing its progress are separate operations. Live A2A updates provide prompt feedback; persisted task projections provide the canonical state used to reconcile a reconnect.

Acceptance is not completion

SendMessage is unary. It returns the first admitted task identity with accepted=true, without waiting for the run to finish or for a durable stream cursor. A bounded wait that ends before acceptance is known is an ambiguous outcome, not permission to resend with a new idempotency key. Retry the same operation identity.

StreamRunEvents observes progress. Other StreamGet* and StreamList* RPCs publish snapshots for agents, sessions, billing, brokerage and operator views. There are more streams than the original four-method API. See Services.

Mutable projections, not a lossless event journal

The pinned kagent public API exposes session/task projections. It does not expose its internal append-only journal as a platform replay API. A cursor therefore identifies a session, projection revision and offset. If the persisted projection changes, reading it again starts that revision; clients upsert stable event identities and revisions rather than append every frame as new history.

Live A2A output is provisional and cursorless. The adapter assembles artifact updates and reconciles against persisted tasks periodically and at stream termination. Canonical replacement prevents a replayed artifact from duplicating provisional text. A late preview is replaced by the canonical value even when the persisted revision has not changed. Reconnect refreshes canonical values once; replacement frames may be cursorless, with the checkpoint carrying the durable progress. A terminal status from an earlier task does not suppress attachment to the current task. An append without a known artifact baseline is withheld until canonical content is available.

This recovers the observable task projection. It does not promise every intermediate status, gap-free token history or exact replay of transient frames. Bounded reads report incompleteness explicitly; a capped result cannot be described as a complete history.

Checkpoints and client state

Checkpoints include observed_at, caught_up, the durable cursor when available and reconciliation cadence. Their freshness means a successful persisted-state read, not a producer processing watermark. A fresh observation can still report incomplete coverage.

The console separates provisional updates from canonical events, retains a draft until its matching submission is accepted, and treats absent counts as unavailable. Available but incomplete counts are lower bounds. Errors and disconnects remain visible while reconnection uses the last durable cursor.

These adapter and console changes have local verification; this documentation update does not establish that the corresponding API and UI builds are deployed.

Session identity across agent recreation

A new session is durably bound to the tenant namespace, owner and immutable agent UID before its first message is sent. New messages, human-input replies and approvals must match that binding and the current agent incarnation. Reusing an agent name does not let an old session address its replacement. Legacy sessions without a binding remain readable but cannot admit new work; create a new session. Replaying an already accepted idempotent submission returns its saved acknowledgement without starting work again.

Tool approval

Agents are long running and autonomous and cannot ask the user anything: the runtime image removes kagent’s ask_user tool, and the contract has no question type (PendingInput.ask_user and HumanInputReply.ask_user are reserved). The one pending interaction is a tool approval. It arises only from an MCP tool binding with requireApproval, which CreateAgent never sets and an imported bundle can carry. It carries the tools awaiting a decision plus the session/task/request identities needed to answer the right interrupt. A reply is bound to that pending request and resumes the existing task. Approval uses the pending approval ID, not an arbitrary tool-call ID. Delegated requests can carry a child confirmation ID while the parent task is the one resumed.

ApproveTool and idempotent message submission are implemented. The current upstream human-in-the-loop documentation explains the extension; the pinned adapter determines the platform’s exact wire handling.

Transport and timeouts

All public streams are server-streaming. Clients must inspect terminal stream errors, including errors delivered after the initial response, rather than trusting HTTP status alone. The API keeps its HTTP server write timeout disabled for long-running streams and uses request-level bounds. The GKE backend timeout is configured for long responses. A dropped connection still requires reconciliation; neither timeout settings nor a cursor make the live transport durable.