Skip to main content
An agent can pause for a human decision or a frontend tool result. Harnest ends that transport run and keeps the original invocation waiting. Your client supplies the result in a new run on the same threadId. Pending interactions block new user input. Harnest validates the authenticated user, thread ownership, expiry, and one-time delivery before resuming. Repeated or unmatched submissions are rejected without repeating the action.

Human approval

When an agent requests approval, Harnest emits state and message snapshots, then RUN_FINISHED with an interrupt outcome. Show the decision in your UI and send a response for every open interrupt:
Argument edits are not accepted. Changed arguments require a new approval. See Human approvals for requesting a decision from agent code.

Browser tools

Declare a capability with @client_tool in your Harnest agent and register its handler in the frontend. Harnest emits the tool call and finishes the transport run without an interrupt outcome, allowing the frontend handler to execute automatically. Append a standard AG-UI tool message to the current history and send it in a new run on the same thread. The appended message has this shape:
content must be a string. Harnest decodes JSON strings before validating the tool’s output contract and resuming the original invocation. Keep the current message history and state in the request so snapshots retain the conversation. The optional CUSTOM event named harnest.client_tool also supplies a request ID. Custom clients can submit that ID as resume[].interruptId, with status: "resolved" and the tool output in payload.

Private client input

@client_input ends the run with an interrupt whose reason is private_input. Its responseSchema describes the private form, and metadata.harnest.privateInput is true. Render a private form and submit its value only in resume[].payload:
Omit messages and state from this resume. Harnest rejects private resumes containing either non-empty field, because transcript messages and state can be echoed in AG-UI snapshots. Do not append the value as a tool message or register this interaction as an automatic frontend tool result. Clear the form value after submission and exclude it from client logging and analytics. Harnest delivers the value once to the trusted application handler. The handler must return None; only its separately declared response can become a model tool result. Cancellation uses status: "cancelled" without a payload. If the serving process restarts, begin a new interaction instead of replaying private input.

External waits

An external wait emits CUSTOM named harnest.external_wait, then ends the transport run with result.status: "in_progress". Poll the supplied response ID using the same session and authenticated user:
Continue until the response completes or fails. See Response status and recovery and Durable execution for storage and recovery behavior.

Serving-process lifetime

Approvals and client-tool waits retain the process-local continuation lifetime. Resume them on the serving process that owns the suspended invocation. Restarting that process does not preserve the pending exchange, even when other session or completion data uses durable storage.