Documentation
¶
Overview ¶
This sample demonstrates serving agents as plain HTTP endpoints.
Agents are bidirectional streaming actions, but the standard action handler also runs them one turn per request: "data" carries the user message, and the optional "init" carries the session source that spans requests.
Two agents show the two ways to hold session state:
- chat has a session store, so the server keeps the state. Each turn persists a snapshot and the response carries sessionId and snapshotId; resume with {"init": {"sessionId": ...}}. The store also brings the companion actions, served under the agent's own path as getSnapshot and abort.
- statelessChat has no store, so the client keeps the state. The response carries the whole thing; send it back as {"init": {"state": ...}}.
Failures come in two tiers. A failed turn still returns 200, reporting finishReason "failed" with a structured error and the last-good state, so a client can retry without losing the conversation. A rejected init (unknown session, or state sent to a store-backed agent) fails the request with a 4xx before any turn runs.
Run it:
go run .
Or with the Dev UI, to call the agents from a browser and read a trace of every turn at http://localhost:4000/traces:
curl -sL cli.genkit.dev | bash # install the Genkit CLI, once genkit start -- go run .
Or over HTTP. Start a conversation, then continue it with the sessionId the response carried:
curl -X POST http://localhost:8080/agents/chat \
-H "Content-Type: application/json" \
-d '{"data": {"message": {"role": "user", "content": [{"text": "My name is Alex and I am planning a trip to Japan."}]}}}'
curl -X POST http://localhost:8080/agents/chat \
-H "Content-Type: application/json" \
-d '{"data": {"message": {"role": "user", "content": [{"text": "What is my name?"}]}}, "init": {"sessionId": "SESSION_ID"}}'
Stream a turn's chunks and lifecycle events as server-sent events:
curl -N -X POST 'http://localhost:8080/agents/chat?stream=true' \
-H "Content-Type: application/json" \
-d '{"data": {"message": {"role": "user", "content": [{"text": "Suggest three day trips from Tokyo."}]}}}'
Or detach, which returns immediately with finishReason "detached" and a pending snapshotId while the turn keeps running. Poll getSnapshot until its status leaves "pending", or abort it:
curl -X POST http://localhost:8080/agents/chat \
-H "Content-Type: application/json" \
-d '{"data": {"message": {"role": "user", "content": [{"text": "Plan a two-week Japan itinerary."}]}, "detach": true}}'
curl -X POST http://localhost:8080/agents/chat/getSnapshot \
-H "Content-Type: application/json" \
-d '{"data": {"snapshotId": "SNAPSHOT_ID"}}'
Or stop the background turn instead, which finalizes it as "aborted":
curl -X POST http://localhost:8080/agents/chat/abort \
-H "Content-Type: application/json" \
-d '{"data": {"snapshotId": "SNAPSHOT_ID"}}'