Skip to main content

agentrs_core/
error.rs

1//! Shared SDK error types.
2
3use std::error::Error as StdError;
4
5/// Common boxed error type.
6pub type BoxError = Box<dyn StdError + Send + Sync>;
7
8/// Shared result type across the SDK.
9pub type Result<T> = std::result::Result<T, AgentError>;
10
11/// Errors produced by LLM providers.
12#[derive(Debug, thiserror::Error)]
13pub enum ProviderError {
14    /// The provider is missing an API key.
15    #[error("Missing API key - set {env_var}")]
16    MissingApiKey {
17        /// Name of the required environment variable.
18        env_var: &'static str,
19    },
20    /// A transport-level failure occurred.
21    #[error("HTTP request failed: {0}")]
22    Http(String),
23    /// The remote API returned an error.
24    #[error("API error {status}: {message}")]
25    Api {
26        /// HTTP status code returned by the provider.
27        status: u16,
28        /// Provider response body or error message.
29        message: String,
30    },
31    /// The provider response could not be parsed.
32    #[error("Response parsing failed: {0}")]
33    Parse(#[from] serde_json::Error),
34    /// The provider reported rate limiting.
35    #[error("Rate limited - retry after {retry_after_secs}s")]
36    RateLimited {
37        /// Suggested retry delay in seconds.
38        retry_after_secs: u64,
39    },
40    /// The model context window was exceeded.
41    #[error("Context window exceeded")]
42    ContextWindowExceeded,
43    /// The provider returned an unexpected payload.
44    #[error("Invalid provider response: {0}")]
45    InvalidResponse(String),
46    /// The requested feature is not supported by the provider.
47    #[error("Unsupported provider feature: {0}")]
48    Unsupported(&'static str),
49}
50
51/// Errors produced by tool execution.
52#[derive(Debug, thiserror::Error)]
53pub enum ToolError {
54    /// The input payload did not match the tool schema.
55    #[error("Invalid tool input: {0}")]
56    InvalidInput(String),
57    /// Tool execution failed.
58    #[error("Tool execution failed: {0}")]
59    Execution(String),
60    /// The tool operation timed out.
61    #[error("Tool execution timed out")]
62    Timeout,
63    /// The tool attempted a forbidden operation.
64    #[error("Permission denied: {0}")]
65    PermissionDenied(String),
66}
67
68/// Errors produced by memory backends.
69#[derive(Debug, thiserror::Error)]
70pub enum MemoryError {
71    /// The backend failed.
72    #[error("Memory backend failed: {0}")]
73    Backend(String),
74    /// Serialization failed.
75    #[error("Memory serialization failed: {0}")]
76    Serialization(#[from] serde_json::Error),
77}
78
79/// Errors produced by MCP clients or adapters.
80#[derive(Debug, thiserror::Error)]
81pub enum McpError {
82    /// The provided command string was invalid.
83    #[error("Invalid MCP command")]
84    InvalidCommand,
85    /// Spawning the MCP server failed.
86    #[error("Failed to spawn MCP server: {0}")]
87    SpawnFailed(String),
88    /// Framing or protocol parsing failed.
89    #[error("MCP protocol error: {0}")]
90    Protocol(String),
91    /// The MCP server reported an error.
92    #[error("MCP response error: {0}")]
93    Response(String),
94    /// The request timed out.
95    #[error("MCP request timed out")]
96    Timeout,
97}
98
99/// Top-level SDK error.
100#[derive(Debug, thiserror::Error)]
101pub enum AgentError {
102    /// Provider integration failure.
103    #[error("LLM provider error: {0}")]
104    Provider(#[from] ProviderError),
105    /// Tool validation or execution failure.
106    #[error("Tool error: {0}")]
107    ToolError(#[from] ToolError),
108    /// Tool execution failed with contextual tool name.
109    #[error("Tool execution failed '{name}': {source}")]
110    Tool {
111        /// Name of the tool that failed.
112        name: String,
113        #[source]
114        /// Original error returned by the tool.
115        source: BoxError,
116    },
117    /// MCP failure.
118    #[error("MCP error: {0}")]
119    Mcp(#[from] McpError),
120    /// Memory failure.
121    #[error("Memory error: {0}")]
122    Memory(#[from] MemoryError),
123    /// Maximum agent iterations were reached.
124    #[error("Max steps reached: {steps}")]
125    MaxStepsReached {
126        /// Number of steps attempted before stopping.
127        steps: usize,
128    },
129    /// JSON serialization failure.
130    #[error("Serialization error: {0}")]
131    Serde(#[from] serde_json::Error),
132    /// I/O failure.
133    #[error("I/O error: {0}")]
134    Io(#[from] std::io::Error),
135    /// Required field is absent.
136    #[error("Missing required field: {0}")]
137    MissingField(&'static str),
138    /// Agent was built without an LLM.
139    #[error("No LLM provider configured")]
140    NoLlmProvider,
141    /// Requested tool name is unknown.
142    #[error("Tool not found: {0}")]
143    ToolNotFound(String),
144    /// Requested agent name is unknown.
145    #[error("Agent not found: {0}")]
146    AgentNotFound(String),
147    /// Configuration is invalid.
148    #[error("Invalid configuration: {0}")]
149    InvalidConfiguration(String),
150    /// Streaming payload was invalid.
151    #[error("Invalid stream payload")]
152    InvalidStream,
153    /// Context window was exceeded.
154    #[error("Context window exceeded")]
155    ContextWindowExceeded,
156    /// Catch-all error message.
157    #[error("{0}")]
158    Message(String),
159}
160
161impl AgentError {
162    /// Wraps an arbitrary error with tool context.
163    pub fn tool_failure(name: impl Into<String>, source: impl Into<BoxError>) -> Self {
164        Self::Tool {
165            name: name.into(),
166            source: source.into(),
167        }
168    }
169}