Use the HTTP API
The daemon serves a JSON API on 127.0.0.1:4747. The HTTP API reference
lists every route.
Create an API token
Section titled “Create an API token”wardrik token create jon-laptop --subject user:acme/@jonexport TOKEN=wdk_...- The token is printed once. Include it in the
Authorization: Bearer TOKENheader. acme/@jonis the user@jonin the orgacme. A user has full access to agents they own.- Other access needs a binding in
config.yaml. See Organizations, roles, and tokens.
Create an agent
Section titled “Create an agent”curl -s -X POST -H "authorization: Bearer $TOKEN" -H "content-type: application/json" \ http://127.0.0.1:4747/v1/owners/acme%2F%40jon/agents \ -d '{ "name": "triage", "model": "anthropic:claude-sonnet-5", "instructions": "You watch the incident queue, and say what needs an engineer.", "tools": ["linear/*"], "policy": {"ask": ["linear/create_*"]} }'# {"id": "agt_01JF8X5RQ2M3V9ZK0B7Y4T6WHN", "name": "triage", "org": "acme", "owner": "acme/@jon"}
export AGENT=agt_01JF8X5RQ2M3V9ZK0B7Y4T6WHN- The daemon generates the agent ID. Every other route takes it.
{owner}is one URL-encoded segment:acmefor the org,acme%2F%40jonfor the user.- A definition has the keys of an agent file.
PUT /v1/agents/$AGENTreplaces the definition, starting with the next turn.GET /v1/owners/acme/agents?name=triagelooks up an agent by name.
Send a message
Section titled “Send a message”curl -s -X POST -H "authorization: Bearer $TOKEN" -H "content-type: application/json" \ http://127.0.0.1:4747/v1/agents/$AGENT/messages \ -d '{"content": "Which incidents need attention?"}'# {"message": {"id": "msg_01…", "cursor": "W1siYWd0XzAxSkY4…"}}The request returns 202 with a message ID and event cursor. Save the returned cursor
as CURSOR for the next step. To use a separate conversation, post to
/v1/agents/$AGENT/conversations/C1/messages.
Stream the reply
Section titled “Stream the reply”export CURSOR=... # copy message.cursor from the response abovecurl -N -H "authorization: Bearer $TOKEN" -H "accept: text/event-stream" \ "http://127.0.0.1:4747/v1/agents/$AGENT/events?after=$CURSOR"- Pass the message's
cursorasafterto receive every event of its turn. - The reply arrives as
wardrik.message.deltaevents, thenwardrik.message.completedandwardrik.run.completed. - Without
accept: text/event-stream, it returns one page of JSON. See Events.
Approve tool calls
Section titled “Approve tool calls”A call that needs approval emits wardrik.run.interrupted, with an id for each call:
curl -s -X POST -H "authorization: Bearer $TOKEN" -H "content-type: application/json" \ http://127.0.0.1:4747/v1/agents/$AGENT/decisions \ -d '{"decisions": [{"id": "call_1", "decision": "approve", "note": "Label it for the next sprint."}]}'"decision": "reject"with a"reason"denies it.POST .../interrupts/{id}/approveand.../denyact on one call.- The model receives the
notewith the result. See Approvals.
With the TypeScript SDK
Section titled “With the TypeScript SDK”import { Wardrik } from "@wardrik/sdk";
const wardrik = new Wardrik(); // WARDRIK_URL, else http://127.0.0.1:4747; WARDRIK_TOKENconst agent = wardrik.agent(process.env.AGENT!);
for await (const event of agent.stream("Which incidents need attention?")) { if (event.type === "wardrik.message.delta") process.stdout.write(event.data.delta);
if (event.type === "wardrik.run.interrupted") { for (const interrupt of event.data.interrupts) { console.log("Approval required:", interrupt); } }}- The SDK example displays pending approvals. Review them with
wardrik approval, or use the approval endpoints to add approval controls to your app. agent.reply("...")resolves when the turn ends or pauses for approval.- The SDK covers Wardrik's routes. For the daemon-only routes (
/v1/owners,/v1/connections,/v1/tokens), usefetch. - It also serves tools from your app. See Tools in your app.
Errors return {"error": {"type": ..., "message": ...}}. Cancel, stop, remove, triggers and every
other route are in the HTTP API reference.