Skip to main content
Call your agent through the same HTTP API whether it uses ADK or LangGraph. The default address is http://127.0.0.1:1907.

Send your first request

From your agent folder, run harnest serve .. In another terminal:
You do not need to create a session first. Read outputText for the answer and keep the returned sessionId for follow-up turns. This is Harnest’s API: send input, not an OpenAI messages array, and configure the model on the agent rather than in this request. Continue the conversation, replacing the placeholder with the returned ID:
For streaming, -N disables curl’s output buffering:
Inspect status, not just the HTTP status code. A response can be completed, in_progress, or requires_action; see response recovery and approvals and client tools.
These commands target a local agent without authentication. For a protected deployment, use the authentication configured by its owner; for bearer authentication, add -H "Authorization: Bearer $HARNEST_TOKEN". Do not put credentials in metadata.

Discover the API

Coding agents should fetch /agent for enabled routes and its resources list. Each spec resource provides a relative uri, name, and mimeType; resolve the URI against the server address and fetch JSON or YAML according to your client’s parser. Both contain the same machine-readable request and response schemas, including custom HTTP routes. Find POST /responses (operation ID createAgentResponse) and inspect requestBody.content.application/json, including its input schema. Typed-input agents may require fields beyond a message string. harnest serve . prints the Swagger URL and both spec URLs. To save a local copy, use curl --fail-with-body -sS http://127.0.0.1:1907/openapi.yaml -o openapi.yaml. Harnest does not automatically attach the spec to model prompts or create a tool for it. For interactive use, open Swagger UI, expand Send a message to the agent, choose an example, then select Try it out and Execute. Swagger displays the curl request and response. These API docs remain available in compiled deployments without the playground; configured authentication still applies. Set server.openapi: false to disable the documentation routes and stop advertising them.

Endpoints

AG-UI clients

Connect an agent-facing UI through POST /agui. Harnest supports streamed text, shared state, frontend tools, and human approval on ADK and LangGraph. See AG-UI for supported capabilities, client integration, and interaction contracts.

Try the CopilotKit demo

Run the CopilotKit example to test both frameworks with a local React UI, without a model API key.

A2A bindings

Declare an A2A HTTP+JSON or JSON-RPC interface in agent-card.yaml to mount its URL alongside the neutral API. A blocking send returns a direct A2A Message when execution completes without needing task semantics. Streaming, returnImmediately, approval, client-tool, and external durable waits use an A2A Task. The binding also supports explicit task lookup, filtered listing, cancellation, and subscriptions. With OutputPolicy(thinking=True), streaming A2A tasks carry provider-exposed reasoning as working-status messages. Portable lifecycle details remain under metadata.harnest, and final answer text remains a response artifact. See Agent2Agent (A2A) for serving, outbound clients, security, durable @task integration, and replica behavior.

Response modes

Send one request to POST /responses and receive one completed response.

Response status and recovery

Harnest records the latest status for every neutral JSON, SSE, and WebSocket response. Use the server-issued response ID and the same session ID:
The authenticated user and session must both match the original invocation. Harnest returns 404 for a missing or mismatched scope so callers cannot probe another user’s response IDs. Process-local receipts make ordinary completions and required actions recoverable while the server process is running. With a Harnest-owned checkpointer, terminal completion envelopes are also durable across replicas and restarts. Pending human approvals and client-tool exchanges still belong to the process holding the suspended invocation. Advanced mode keeps the same API where Harnest owns the neutral transport. Recovery is best effort when your application replaces the graph, checkpointer, transport, or tool wiring; Harnest leaves those user-owned boundaries alone. All modes use the same portable activity contract. JSON returns these items in output. SSE and WebSocket use the corresponding response.* frames.
thinking is observable agent activity enabled by OutputPolicy(thinking=True). It is suppressed by default and is never part of outputText, the committed conversation transcript, or evaluation answer text. Providers do not always expose readable reasoning, so a response may contain no thinking events even after opting in. agent_activity identifies the normalized agent or LangGraph node and lifecycle transition, such as started, completed, handoff, interrupted, or failed. Message and tool events can also include an agent field. By default Harnest does not forward provider signatures, credentials, framework objects, graph state, or native event metadata through this contract. decision_result is opt-in output from context.decisions.evaluate(...). Enable it with OutputPolicy(decision_results=True). Each item has an optional agent and a value containing decision, version, provider, providerVersion, answers, outcome, durationSeconds, and error. Streaming uses response.decision_result with the same agent and value. Decision events do not contribute to outputText; hiding them does not prevent internal routing or remove fields explicitly copied into the final result. agent_metadata centralizes metadata for each reported model call. usage contains exact provider counts; Harnest does not estimate missing values. model, provider, and finishReason appear only when reported, and the finish-reason value keeps the provider’s vocabulary. A completed JSON, SSE, or WebSocket response also includes top-level usage aggregated across its agent_metadata events. This is distinct from the response’s metadata, which is caller-supplied invocation metadata. Use OutputPolicy(agent_metadata=AgentMetadataMode.SUPPRESS) to omit every per-call metadata event and the top-level aggregate usage. Use OutputPolicy(tool_activity=False) to omit public tool_call and tool_result activity without disabling the underlying tool execution. These controls apply before JSON, SSE, WebSocket, local, playground, and durable result projection. By default Harnest omits native metadata fields. Configure OutputPolicy(agent_metadata=AgentMetadataMode.RAW) to add a raw mapping to each metadata event. See Output policy for the ADK and LangGraph namespaces and the disclosure warning. With a Harnest-owned checkpointer, completion output and normalized agent metadata are stored before the run becomes terminal. Polling from another replica therefore returns the same per-call metadata, aggregate usage, caller metadata, and structured result. Raw metadata is stored only when persist_raw_agent_metadata=True is explicitly combined with raw mode. Native metadata that you explicitly declare in a structured output remains namespaced under adk or langgraph. Treat that metadata as framework-specific rather than part of the portable activity contract. An external or queued durable wait returns status: in_progress. Poll the response ID with the same authenticated user and session until it is completed or failed. See Durable execution. Typed input, output, and media use the same contract in every mode. See Accept multimodal data.

Pagination properties

Malformed or cross-user cursors return 400.

Playground

The playground uses only the neutral API. It supports sessions, state, reasoning and lifecycle activity, tools, JSON, SSE, and opt-in WebSocket conversations. Reasoning appears in a separate collapsible panel, never in the assistant answer. Its Live transport choice is disabled when the server does not advertise /live. Open /?session=<id> to select an owned session and restore its transcript. The session picker filters its bounded list by ID; enter a complete ID to load an owned session outside that page. Selecting or creating a session updates the URL. Browsers cannot add arbitrary authorization headers to a WebSocket handshake.