simple-agent-type 0.2.0

Core types and traits for SimpleAgents
Documentation

simple-agent-type

Core types and traits for the SimpleAgents LLM framework.

Overview

simple-agent-type is the foundational crate of SimpleAgents, providing all core types, traits, and error definitions. It has zero runtime dependencies - no HTTP client, no I/O, no async runtime - just pure types and traits.

Features

  • Type Safety: Strong types prevent common errors
  • Transparency: All transformations tracked via CoercionFlag
  • Security: API keys never logged (via secure ApiKey type)
  • Validation: Early validation with clear error messages
  • Async: All traits use async_trait for async support
  • Serialization: Full serde support for all types

Architecture

SimpleAgents follows a trait-based architecture with three main traits:

  1. Provider - LLM provider implementations (OpenAI, Anthropic, etc.)
  2. Cache - Response caching (in-memory, Redis, etc.)
  3. RoutingStrategy - Provider selection logic (round-robin, latency-based, etc.)

Quick Start

use simple_agent_type::prelude::*;

// Create a request
let request = CompletionRequest::builder()
    .model("gpt-4")
    .message(Message::user("Hello, world!"))
    .temperature(0.7)
    .build()
    .unwrap();

// Access request properties
assert_eq!(request.model, "gpt-4");
assert_eq!(request.messages.len(), 1);

Core Types

Messages

use simple_agent_type::message::{Message, Role};

let user_msg = Message::user("What is 2+2?");
let assistant_msg = Message::assistant("4");
let system_msg = Message::system("You are a helpful assistant.");

Requests

use simple_agent_type::request::CompletionRequest;
use simple_agent_type::message::Message;

let request = CompletionRequest::builder()
    .model("gpt-4")
    .message(Message::user("Hello!"))
    .temperature(0.7)
    .max_tokens(100)
    .build()?;

Responses

use simple_agent_type::response::CompletionResponse;

// Get the first completion's content
if let Some(content) = response.content() {
    println!("Response: {}", content);
}

Error Handling

use simple_agent_type::error::{SimpleAgentsError, ProviderError};

match result {
    Ok(response) => println!("{}", response.content().unwrap()),
    Err(SimpleAgentsError::Provider(ProviderError::RateLimit { retry_after })) => {
        println!("Rate limited, retry after {:?}", retry_after);
    }
    Err(e) => eprintln!("Error: {}", e),
}

API Key Security

use simple_agent_type::validation::ApiKey;

let key = ApiKey::new("sk-...")?;

// Never logged
println!("{:?}", key); // Output: ApiKey([REDACTED])

// Explicit access only
let raw_key = key.expose(); // Use for API calls only

Coercion Tracking

use simple_agent_type::coercion::{CoercionResult, CoercionFlag};

let result = CoercionResult::new(42)
    .with_flag(CoercionFlag::StrippedMarkdown)
    .set_confidence(0.95);

if result.was_coerced() {
    println!("Applied {} coercions", result.flags.len());
}

Module Structure

  • message - Message types (Role, Message)
  • request - Request types (CompletionRequest, builder)
  • response - Response types (CompletionResponse, Usage, streaming)
  • error - Error hierarchy (SimpleAgentsError, ProviderError, HealingError)
  • provider - Provider trait and types
  • cache - Cache trait
  • router - Routing strategy trait
  • config - Configuration types (RetryConfig, HealingConfig, Capabilities)
  • validation - Validation types (ApiKey)
  • coercion - Coercion tracking (CoercionFlag, CoercionResult)

Traits

Provider Trait

use simple_agent_type::provider::Provider;
use async_trait::async_trait;

#[async_trait]
impl Provider for MyProvider {
    fn name(&self) -> &str { "my-provider" }

    fn transform_request(&self, req: &CompletionRequest) -> Result<ProviderRequest> {
        // Transform to provider format
    }

    async fn execute(&self, req: ProviderRequest) -> Result<ProviderResponse> {
        // Make HTTP request
    }

    fn transform_response(&self, resp: ProviderResponse) -> Result<CompletionResponse> {
        // Transform from provider format
    }
}

Cache Trait

use simple_agent_type::cache::Cache;
use async_trait::async_trait;

#[async_trait]
impl Cache for MyCache {
    async fn get(&self, key: &str) -> Result<Option<Vec<u8>>> { /* ... */ }
    async fn set(&self, key: &str, value: Vec<u8>, ttl: Duration) -> Result<()> { /* ... */ }
    async fn delete(&self, key: &str) -> Result<()> { /* ... */ }
    async fn clear(&self) -> Result<()> { /* ... */ }
}

RoutingStrategy Trait

use simple_agent_type::router::RoutingStrategy;
use async_trait::async_trait;

#[async_trait]
impl RoutingStrategy for MyRouter {
    async fn select_provider(
        &self,
        providers: &[ProviderConfig],
        request: &CompletionRequest,
    ) -> Result<usize> {
        // Select provider index
    }
}

Design Principles

  1. Transparency First - Every transformation is tracked
  2. Type Safety - Strong types prevent errors
  3. Performance - Zero-cost abstractions
  4. Fail Fast - Validate early, error clearly
  5. Security - Sensitive data never logged

Testing

All types include comprehensive unit tests:

cargo test

Run clippy and format checks:

cargo clippy -- -D warnings
cargo fmt -- --check

Dependencies

Minimal dependencies for maximum compatibility:

  • serde - Serialization
  • serde_json - JSON support
  • thiserror - Error handling
  • async-trait - Async trait support

License

MIT OR Apache-2.0

Next Steps

After simple-agent-type, the next crates to implement are:

  1. simple-agents-providers - OpenAI, Anthropic, etc.
  2. simple-agents-healing - JSON parser with coercion
  3. simple-agents-router - Retry and fallback logic
  4. simple-agents-core - Client and completion API