Skip to main content
The Agent class includes a powerful RPC (Remote Procedure Call) system that allows you to expose methods as callable Actions. This brings a structured, ergonomic, and type-safe approach to agent communication, moving beyond simple message passing.

What is an Action?

An Action is a Python method on your Agent subclass that is decorated with @action. This decorator registers the method with the agent’s RPC system, making it callable by external clients (HTTP, WebSocket) and other agents.

How to Call Actions

Actions can be called through multiple transports, making them highly versatile.

1. Via REST API (HTTP)

AgentServer and AgentRouter automatically create a REST endpoint for each action.
  • URL: POST /agent/{agent_id}/action/{action_name}
  • Body: JSON payload with action parameters.

2. Via WebSocket

For stateful clients, actions can be called over an existing WebSocket connection.
The agent will send an action_result event with the same call_id upon completion.

3. Agent-to-Agent (Location Transparent RPC)

Use self.call() to get a type-safe proxy for communicating with another agent, regardless of whether it’s running locally or on a remote server. Local Example:
Remote Example: Now, imagine support-agent-1 is deployed as a serverless function. With the Agent Registry, your ManagerAgent code does not change.
The self.call("support-agent-1") inside ManagerAgent is automatically routed over HTTP, but your business logic remains clean and unaware of the network. This is Location Transparency. Local calls are routed through the target agent’s mailbox. The server creates and starts the target agent when needed, and the target handles one mailbox operation at a time. When a call supplies an AbortSignal, the same signal is available to the target action as self.context.signal, so delegated work can pass it to model turns or other cancellable operations. Set timeout=None for work whose lifecycle is bounded by the abort signal rather than a wall-clock deadline. After that signal aborts, local calls allow up to one second for cooperative target cleanup before ending the caller-side wait. Once the signal aborts, a target success returned during that cleanup grace period is discarded rather than overriding the abort.

Observe Local Call Events

Local calls can observe the target agent’s emitted events while its action is running. The handler receives each Event in emission order, and each handler call finishes before the delegated action can complete:
The observer is scoped to that mailbox invocation and is deactivated on success, failure, timeout, or cancellation. Detached tasks retain their originating invocation context and cannot leak events into a later call. Observer exceptions are logged and do not replace the action’s primary result. Event handlers must not re-enter emit() on the target agent; attempted re-entry is rejected instead of deadlocking. Transports opt into this API with supports_call_events = True. HTTPTransport, DurableObjectTransport, and legacy custom transports do not support on_event; they raise NotImplementedError when it is requested.

Multi-User Metadata (Connection State)

A key feature of the RPC system is its awareness of the caller. You can store metadata on a per-connection basis without polluting the agent’s main state.

How it Works

  1. on_connect: When a client connects, you can store information in connection.state.
  2. self.context: When an action is executed, self.context.connection provides access to the state of the specific client who made the call.

Example: A Multi-User Chat Room

In this example, if two different users call the who_am_i action, they will each get their own user_id back, because the agent can distinguish between them using self.context.