Skip to main content

AgentExecutor

Trait AgentExecutor 

Source
pub trait AgentExecutor:
    Send
    + Sync
    + 'static {
    // Required method
    fn execute<'a>(
        &'a self,
        ctx: &'a RequestContext,
        queue: &'a dyn EventQueueWriter,
    ) -> Pin<Box<dyn Future<Output = A2aResult<()>> + Send + 'a>>;

    // Provided methods
    fn cancel<'a>(
        &'a self,
        ctx: &'a RequestContext,
        queue: &'a dyn EventQueueWriter,
    ) -> Pin<Box<dyn Future<Output = A2aResult<()>> + Send + 'a>> { ... }
    fn on_shutdown<'a>(
        &'a self,
    ) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> { ... }
}
Expand description

Trait for implementing A2A agent execution logic.

Implementors process incoming messages by writing events (status updates, artifacts) to the provided EventQueueWriter. The executor runs in a spawned task and should signal completion by writing a terminal status update and returning Ok(()).

§Object safety

This trait is object-safe: methods return Pin<Box<dyn Future>> so that executors can be used as Arc<dyn AgentExecutor>. This eliminates the need for generic parameters on RequestHandler, RestDispatcher, and JsonRpcDispatcher, simplifying the entire server API surface.

§Example

use std::pin::Pin;
use std::future::Future;
use a2a_protocol_server::executor::AgentExecutor;
use a2a_protocol_server::request_context::RequestContext;
use a2a_protocol_server::streaming::EventQueueWriter;
use a2a_protocol_types::error::A2aResult;

struct MyAgent;

impl AgentExecutor for MyAgent {
    fn execute<'a>(
        &'a self,
        ctx: &'a RequestContext,
        queue: &'a dyn EventQueueWriter,
    ) -> Pin<Box<dyn Future<Output = A2aResult<()>> + Send + 'a>> {
        Box::pin(async move {
            // Write status updates and artifacts to `queue`.
            Ok(())
        })
    }
}

§Ergonomic helpers

Use boxed_future to reduce boilerplate, or the agent_executor! macro for a fully declarative approach:

use a2a_protocol_server::agent_executor;

struct EchoAgent;

agent_executor!(EchoAgent, |_ctx, _queue| async {
    Ok(())
});

Required Methods§

Source

fn execute<'a>( &'a self, ctx: &'a RequestContext, queue: &'a dyn EventQueueWriter, ) -> Pin<Box<dyn Future<Output = A2aResult<()>> + Send + 'a>>

Executes agent logic for the given request.

Write StreamResponse events to queue as the agent progresses. The method should return Ok(()) after writing the final event, or Err(...) on failure.

§Errors

Returns an A2aError if execution fails.

Provided Methods§

Source

fn cancel<'a>( &'a self, ctx: &'a RequestContext, queue: &'a dyn EventQueueWriter, ) -> Pin<Box<dyn Future<Output = A2aResult<()>> + Send + 'a>>

Cancels an in-progress task.

The default implementation cancels. It emits the terminal Canceled status so subscribers see it, best-effort: a task with no live subscribers has no queue receivers, and that must not fail the cancel, because the handler persists the state either way. Cancellation in A2A is cooperative — by the time this runs the handler has already triggered RequestContext::cancellation_token, which a running execute is expected to observe.

Override this when the task holds something that must be released — a reserved slot, a parked message, an open handle. Overriding is about releasing state, not about opting in to cancellation.

Before 0.7 the default refused with TaskNotCancelable, which left Working tasks uncancelable out of the box and reported it as the task’s fault. Every reference SDK requires agents to support cancel.

§Errors

Returns an A2aError if an override fails to release what the task holds. The default implementation does not return an error.

Source

fn on_shutdown<'a>(&'a self) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>>

Called during handler shutdown to allow cleanup of external resources (database connections, file handles, etc.).

The default implementation is a no-op.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§