Skip to main content

A2aServer

Struct A2aServer 

Source
pub struct A2aServer { /* private fields */ }
Expand description

This plane, served as an A2A agent.

Implementations§

Source§

impl A2aServer

Source

pub fn new( runtime: Arc<Runtime>, auth: Arc<dyn Authenticator>, security: &CardSecurity, manifest: &Manifest, url: impl Into<String>, ) -> Result<Self, ServerSetupError>

Serve manifest’s agent at url.

url is where callers reach this plane, and it goes on the card — the same deployment-wiring split as everywhere else: an agent’s declaration must not change when its address does.

§Errors

ServerSetupError::NoPolicy when the runtime has no policy engine, and ServerSetupError::Card when the manifest’s digest cannot be computed.

Source

pub fn hosting( runtime: Arc<Runtime>, auth: Arc<dyn Authenticator>, security: &CardSecurity, manifests: &[&Manifest], url: impl Into<String>, ) -> Result<Self, ServerSetupError>

Serve several declared agents from one plane.

A2A’s well-known card path is singular per host, so the alternative to this is a server per agent. The first manifest is the one the well-known card describes — a room’s orchestrator, in the shape the CLI already uses — and every agent additionally gets its own full card at agent_card_path, listed in the EXT_AGENT_DIRECTORY extension so a caller can find them.

Skill dispatch spans every agent, because they are all on the runtime already — what was missing was only discovery. Two agents advertising one skill id is refused: dispatch names a skill, and a name that resolves to two agents is a routing decision the caller did not make.

§Errors

ServerSetupError::NoPolicy, ServerSetupError::NoCases, ServerSetupError::NoAgents for an empty slice, or ServerSetupError::AmbiguousSkill.

Source

pub fn streams_per_caller(self, limit: usize) -> Self

Bound how many streams one caller may hold open at once.

A SendStreamingMessage or SubscribeToTask is a connection held for as long as the run lives and a journal read per poll interval — so an unbounded count is a cost any authenticated peer chooses for this plane. Past the ceiling a new stream is refused as back-pressure (code::QUOTA_EXHAUSTED), before anything is admitted; one ending, or its client going away, frees the slot.

Source

pub fn filter_scan_budget(self, budget: usize) -> Self

Bound what one ListTasks may cost.

The spec’s totalSize is the exact total, and a status or contextId filter is decided only by reading each candidate’s journal — so the cost of a listing is one the caller chooses.

The budget counts the caller’s own tasks. The index a listing reads is narrowed to them, so another caller’s volume — or the embedder’s — does not refuse this one’s listing.

Over budget, the request is refused with the narrowing lever named — statusTimestampAfter is answered from the index, so tightening it shrinks the candidate set without reading anything. A refusal is honest where a truncated total would be a lie shaped like an answer: the spec requires the exact count, and a bound that quietly stopped counting would report a smaller tenant, not a bounded scan.

Source

pub fn artifact_replay_budget(self, budget: usize) -> Self

Bound what one ListTasks with includeArtifacts may cost.

A completed task’s artifacts are recovered by strict replay, and a page holds up to a hundred tasks — so without a ceiling, one authenticated request buys a hundred full replays, per request, forever. Replays served from the sealed-run cache cost nothing and do not count; past the budget a task’s artifacts are omitted and marked (see ARTIFACTS_OMITTED_KEY) rather than the request refused, because unlike totalSize an artifact list is per-task enrichment: omitting one is honest as long as it does not look complete, and GetTask on the marked id recovers exactly that task’s artifacts.

Source

pub fn signing_cards_with( self, signer: &dyn CardSigner, ) -> Result<Self, CardSignatureError>

Publish a signed card.

The card is served unauthenticated from a host a caller may not control. TLS says the bytes came from that host; it says nothing about whether the host is the party whose capabilities the card describes. A signature says that, and it keeps saying it after the card has been copied into a registry, a cache, or somebody’s repository.

Signed here rather than at derivation because the signature covers the published card, interface URL and tenant included — those are deployment facts, and a signature taken before they were set would cover a document nobody serves.

§Errors

If the card cannot be canonicalized.

Source

pub fn with_push( self, store: Arc<dyn PushStore>, transport: Arc<dyn PushTransport>, ) -> Result<Self, ServerSetupError>

Enable A2A push configuration and expose a durable delivery worker.

The worker uses the task journal itself as its outbox. A registration’s cursor advances only after a receiver returns 2xx, so a crash between POST and acknowledgement persistence repeats an event and never loses one. Call A2aServer::push_worker before consuming the server into its router and schedule DeliveryWorker::run_once from every instance.

Source

pub fn push_worker(&self) -> Option<A2aPushWorker>

A cloneable worker handle, when push is configured.

The worker is crate::push::DeliveryWorker itself, bound to the A2A projection — rows belonging to an operator Outbox are left alone, because the projection declares the caller namespace and the store’s due query filters on it. Retry ceiling, backoff and abandonment reporting are the loop’s own; see its docs rather than a restatement here.

Source

pub fn router(self) -> Router

The router.

The card path is unauthenticated by design and everything else is not.

The RPC endpoint answers with and without a trailing slash, and that is an interoperability fact rather than a courtesy: mainstream HTTP clients that take a base URL — httpx among them, which is what the official A2A conformance kit and the reference Python SDK are built on — resolve a request for "/" against the card’s interface URL per RFC 3986, so the wire carries POST {interface}/. A router that 404s the slash form passes every test written here and fails the first real peer. Exactness elsewhere (method names, version headers) guards protocol semantics; a trailing slash is a client-side join artifact with none.

Trait Implementations§

Source§

impl Clone for A2aServer

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for A2aServer

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<Unshared, Shared> IntoShared<Shared> for Unshared
where Shared: FromUnshared<Unshared>,

Source§

fn into_shared(self) -> Shared

Creates a shared type from an unshared type.
Source§

impl<T> MaybeSend for T
where T: Send,

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more