Skip to main content
Use @client_tool when the connected client—not the agent server—owns execution.
Harnest never executes the declaration body. It suspends the invocation and asks the client to run the tool.

Client-tool properties

Transport flow

The submitted result is identity-bound, one-time, and validated against the declared return type. When an invocation has an Agent Runtime Principal, Harnest presents the client tool only when it declares a permission carried by the principal and checks again before requesting client execution. Untagged client tools are unavailable. The client must still authorize the local action.

Private client input

Use @client_input to collect a password, token, or other private client value for trusted application code. Harnest delivers the validated input to the handler and exposes only a separately declared response to the model.
connect_account is your application integration. The handler runs on the server, unlike a @client_tool declaration body. Its first positional parameter receives the private Pydantic value; that parameter is absent from the model’s tool schema. Other parameters, such as service, are public arguments sent to the client. Harnest does not infer a safe answer from the handler’s return value. A successful handler yields a fresh copy of the authored response; failures do not yield the success response. Do not stack @tool or @client_tool on this decorator. The guarantee covers Harnest-managed delivery and framework projection. Trusted handler code still controls its own logging, storage, and outbound calls. Do not copy private input into model prompts, public state, or logs. The client must likewise keep the value out of chat history and client telemetry. Ephemeral delivery means Harnest releases its references; it does not promise secure erasure of Python memory or restart recovery. Private prompts use the same JSON, SSE, and WebSocket transport as client tools, with privateInput: true and inputSchema on the requested action. AG-UI uses an explicit private_input interrupt, rather than the automatic frontend tool-result loop.

Combine with approval

@client_tool and @require_human_approval can appear in either decorator order. Approval runs first. After approval, the host receives the client-tool request. @client_input supports the same approval decorator ordering and runtime permission checks.

Human approvals

Bind approval to the exact user, session, invocation, action, and arguments.

Serving agents

Implement approval and client-tool responses over each transport.