Skip to content

prelude

Prelude module for common imports

Core Agent implementation

The Agent struct is the main runtime entry point for registering skills, wiring handlers, and dispatching runtime messages. Protocol surfaces such as A2A and AG-UI compose around this type via adapter modules.

Methods

fn new_runtime(name: &str) -> SdkResult<Self>

Create a new runtime-first agent.

fn new(name: &str) -> SdkResult<Self>

Create a new agent (alias of new_runtime)

fn new_with_config(config: AgentConfig) -> SdkResult<Self>

Create agent with custom configuration

fn with_service<T>(self, service: T) -> Self
fn get_service<T>(&self) -> Option<Arc<T>>
fn has_service<T>(&self) -> bool
fn add_skill(&mut self, skill_id: &str) -> SkillEntryBuilder<'_>

Register a skill via the fluent builder (handler optional — omit for metadata-only).

fn skill<F, Fut>(&mut self, name: &str, handler: F) -> SkillEntryBuilder<'_>
where
F: Fn + Send + Sync + ?,
Fut: Future + Send + ?

Register a skill with a handler (add_skill(name).handler(handler)).

fn register_notification<F, Fut>(&mut self, name: &str, handler: F) -> SdkResult<()>
where
F: Fn + Send + Sync + ?,
Fut: Future + Send + ?

Register a notification handler.

fn config(&self) -> &AgentConfig
fn list_skills(&self) -> Vec<String>
fn list_notifications(&self) -> Vec<String>
fn skill_registry(&self) -> &SkillRegistry

Get read-only reference to the skill registry.

fn set_message_handler<F, Fut>(&mut self, handler: F)
where
F: Fn + Send + Sync + ?,
Fut: Future + Send + ?
async fn dispatch_message(&self, msg_ctx: MessageContext, task_ctx: Option<TaskContext>) -> SdkResult<RuntimeResponse>

Unified entrypoint to route a built MessageContext through the active handler.

Agent Configuration

Configuration for agent behavior, capabilities, and response patterns.

The agent supports different response patterns:

  • Stateful (default): Creates Task responses for conversation continuity
  • Stateless: Prefers lightweight Message responses for API-style interactions
use agent_sdk::agent::AgentConfig;
// Default stateful agent
let config = AgentConfig::default();
// Stateless agent for API-style interactions
let config = AgentConfig::new("api-agent", "API Agent")
.stateless();

Fields

FieldTypeDescription
nameString
descriptionString
versionString
storage_prefixOption&lt;String&gt;Optional storage namespace prefix used by shared task-storage backends.
max_message_sizeu64
streamingbool
batch_processingbool
concurrent_tasksOption&lt;u32&gt;
stateless_methodsboolPrefer stateless responses (Message) over stateful (Task) for methods
base_urlOption&lt;String&gt;Base URL for constructing absolute AgentInterface URLs in the agent card.
history_policyOption&lt;HistoryPolicyConfig&gt;Optional history policy used for durable continuation preparation.

Methods

fn new<impl Into<String>, impl Into<String>>(name: impl Into, description: impl Into) -> Self

Create a new agent configuration

  • name - Agent name
  • description - Agent description
use agent_sdk::agent::AgentConfig;
let config = AgentConfig::new("my-agent", "My Agent Description");
fn stateless(self) -> Self

Configure agent for stateless method responses

When enabled, methods will prefer lightweight Message responses over Task responses for API-style interactions.

use agent_sdk::agent::AgentConfig;
let config = AgentConfig::new("api-agent", "API Agent")
.stateless();
fn stateful(self) -> Self

Configure agent for stateful method responses (default)

Methods will create Task responses for conversation continuity.

use agent_sdk::agent::AgentConfig;
let config = AgentConfig::default()
.stateful(); // Explicit stateful (default behavior)
fn with_base_url<impl Into<String>>(self, url: impl Into) -> Self

Set the base URL for absolute AgentInterface URLs in the agent card.

The A2A v1.0 spec requires absolute URLs in AgentInterface.url. When set, the SDK produces {base_url}/jsonrpc instead of /jsonrpc.

fn with_history_policy(self, policy: HistoryPolicyConfig) -> Self

Attach a history policy for pre/post-turn continuation preparation.

Minimal service container for dependency injection

Allows agents to accept optional services through clean dependency injection without hardcoding specific service fields in the Agent struct.

use agent_sdk::services::ServiceContainer;
use std::sync::Arc;
#[derive(Clone)]
struct MyService {
name: String,
}
let mut container = ServiceContainer::new();
container.register(MyService { name: "test".to_string() });
let service: Option<Arc<MyService>> = container.get();
assert!(service.is_some());

Methods

fn new() -> Self

Create a new empty service container

fn register<T>(&mut self, service: T)

Register a service in the container

Services are stored by their type and can be retrieved later using the same type signature.

  • service - The service instance to register
# use agent_sdk::services::ServiceContainer;
# #[derive(Clone)]
# struct DatabaseService;
let mut container = ServiceContainer::new();
container.register(DatabaseService);
fn get<T>(&self) -> Option<Arc<T>>

Get a service from the container

Returns an Arc-wrapped service if found, or None if the service type is not registered.

  • Some(Arc<T>) - The service if found
  • None - If no service of type T is registered
# use agent_sdk::services::ServiceContainer;
# use std::sync::Arc;
# #[derive(Clone)]
# struct DatabaseService { pub name: String }
# let mut container = ServiceContainer::new();
# container.register(DatabaseService { name: "test".to_string() });
let service: Option<Arc<DatabaseService>> = container.get();
if let Some(db) = service {
println!("Database: {}", db.name);
}
fn has<T>(&self) -> bool

Check if a service type is registered

  • true - If a service of type T is registered
  • false - If no service of type T is found
# use agent_sdk::services::ServiceContainer;
# #[derive(Clone)]
# struct CacheService;
let container = ServiceContainer::new();
assert!(!container.has::<CacheService>());
fn len(&self) -> usize

Get the number of registered services

fn is_empty(&self) -> bool

Check if the container is empty

fn clear(&mut self)

Remove all services from the container

Skill Call Information

Extracted from DataPart when a structured skill call is detected.

Fields

FieldTypeDescription
skill_idString
parametersserde_json::Value

Protocol-independent skill definition.

This is the single source of truth for skill metadata inside the SDK. Protocol adapters (A2A AgentSkill, MCP, etc.) convert from this type.

Fields

FieldTypeDescription
idString
nameString
descriptionString
input_modesVec&lt;String&gt;
output_modesVec&lt;String&gt;
schemaOption&lt;serde_json::Value&gt;
examplesOption&lt;Vec&lt;String&gt;&gt;
tagsOption&lt;Vec&lt;String&gt;&gt;
instructionsOption&lt;String&gt;Behavioral guidance injected into LLM context when this skill is activated.
exposeboolWhether the skill is visible on the discovery card (default: true).
llm_callableboolWhether the LLM can invoke this skill’s handler via read_skill tool (default: false).

Fluent builder for skill registration.

Created via [SkillRegistry::add_skill] / [crate::Agent::add_skill], or [SkillRegistry::skill] / [crate::Agent::skill] when providing a handler. Finalize with .register().

Methods

fn handler<F, Fut>(self, handler: F) -> Self
where
F: Fn + Send + Sync + ?,
Fut: Future + Send + ?

Attach an async handler. Omit for metadata-only skills (discovery card + LLM awareness).

fn display_name<S>(self, name: S) -> Self
fn description<S>(self, desc: S) -> Self
fn schema(self, schema: Value) -> Self
fn examples(self, examples: Vec<String>) -> Self
fn example<S>(self, example: S) -> Self
fn tags(self, tags: &[&str]) -> Self
fn tag<S>(self, tag: S) -> Self
fn input_modes(self, modes: &[&str]) -> Self
fn output_modes(self, modes: &[&str]) -> Self
fn json_only(self) -> Self
fn text_only(self) -> Self
fn instructions<S>(self, text: S) -> Self

Set behavioral instructions (injected into LLM context when skill is activated).

fn expose(self, visible: bool) -> Self

Control whether the skill is visible on the discovery card (default: true).

fn llm_callable(self, callable: bool) -> Self

Control whether the LLM can invoke this skill via read_skill tool (default: false).

fn register(self) -> SdkResult<()>

Finalize registration.

Message Type Classification

Classifies incoming messages based on their Part composition to determine the appropriate handling strategy (tool-like vs conversational vs hybrid).

Variants

VariantDescription
DataPure DataPart - structured tool calls
TextPure TextPart - conversational interactions
MixedMultiple part types - hybrid interactions

SDK-specific error types

Wraps underlying A2A protocol errors and adds SDK-specific error cases for better error handling and user experience.

Variants

VariantDescription
A2AProtocol(error::A2AError)A2A protocol error
Configuration { ... }Configuration error
AgentInitialization { ... }Agent initialization error
SkillRegistration { ... }Skill registration error
MethodExecution { ... }Method execution error
Serialization(serde_json::Error)Serialization error
Io(Error)IO error
Generic(anyhow::Error)Generic error
FeatureNotEnabled { ... }Feature not enabled
InvalidInput { ... }Invalid input

Methods

fn configuration<impl Into<String>>(details: impl Into) -> Self

Create a configuration error

fn agent_initialization<impl Into<String>>(reason: impl Into) -> Self

Create an agent initialization error

fn skill_registration<impl Into<String>, impl Into<String>>(skill: impl Into, reason: impl Into) -> Self

Create a skill registration error

fn method_execution<impl Into<String>, impl Into<String>>(method: impl Into, details: impl Into) -> Self

Create a method execution error

fn feature_not_enabled<impl Into<String>>(feature: impl Into) -> Self

Create a feature not enabled error

fn invalid_input<impl Into<String>>(details: impl Into) -> Self

Create an invalid input error

fn is_recoverable(&self) -> bool

Check if error is recoverable

fn category(&self) -> &''static str

Get error category for monitoring/logging