Crate riglr_core

Crate riglr_core 

Source
Expand description

§riglr-core

Chain-agnostic foundation for the riglr ecosystem, providing core abstractions for multi-blockchain tool orchestration without SDK dependencies.

§Design Philosophy

riglr-core maintains strict chain-agnosticism through:

  • Type Erasure: Blockchain clients stored as Arc<dyn Any>
  • Serialization Boundaries: Transactions passed as bytes/JSON
  • Dependency Injection: ApplicationContext pattern for runtime injection
  • Unidirectional Flow: Tools depend on core, never the reverse

§Architecture Overview

The riglr-core crate provides three main architectural patterns:

§1. Unified Tool Architecture with ApplicationContext

All tools now use a single ApplicationContext parameter that provides access to RPC clients, configuration, and other shared resources. Tools are defined with the #[tool] macro:

use riglr_core::{Tool, ToolError, provider::ApplicationContext};
use riglr_macros::tool;

#[tool]
async fn my_tool(
    param1: String,
    param2: u64,
    context: &ApplicationContext,
) -> Result<serde_json::Value, ToolError> {
    // Access RPC client from context
    // In practice, use concrete types from blockchain SDKs:
    // let rpc_client = context.get_extension::<Arc<MyRpcClient>>()
    //     .ok_or_else(|| ToolError::permanent_string("RPC client not available"))?;

    // Access configuration
    let config = &context.config;

    // Perform operations...
    Ok(serde_json::json!({ "result": "success" }))
}

§2. ToolWorker Lifecycle

Orchestrates tool execution with proper error handling and ApplicationContext:

use riglr_core::{ToolWorker, ExecutionConfig, provider::ApplicationContext};
use riglr_core::idempotency::InMemoryIdempotencyStore;
use riglr_config::Config;
use std::sync::Arc;

let config = Config::from_env();
let context = ApplicationContext::from_config(&config);

let worker = ToolWorker::<InMemoryIdempotencyStore>::new(
    ExecutionConfig::default(),
    context
);

// Execute tools with automatic retry logic
// let result = worker.process_job(job).await?;

§3. ToolError Structure and Classification

The new ToolError structure provides rich error classification with context:

  • Permanent { source, source_message, context }: Non-retriable errors
  • Retriable { source, source_message, context }: Temporary issues that can be retried
  • RateLimited { source, source_message, context, retry_after }: Rate limiting with optional backoff
  • InvalidInput { source, source_message, context }: Input validation failures
  • SignerContext(String): Signer-related errors

§Integration with rig

riglr-core extends rig’s agent capabilities with blockchain-specific tooling while maintaining compatibility with rig’s execution model.

§Key Components

  • SignerContext - Thread-safe signer management for transactional operations
  • UnifiedSigner - Trait for blockchain transaction signing across chains
  • [ApplicationContext] - Dependency injection container with RPC client extensions
  • ToolWorker - Resilient tool execution engine with retry logic and timeouts
  • JobQueue - Distributed job processing with Redis backend
  • Tool - Core trait for defining executable tools with error handling
  • Job - Work unit representation with retry and idempotency support
  • JobResult - Structured results distinguishing success, retriable, and permanent failures
  • [retry_async] - Centralized retry logic with exponential backoff

§Quick Start Example

use riglr_core::{ToolWorker, ExecutionConfig, Job, JobResult, ToolError};
use riglr_core::{idempotency::InMemoryIdempotencyStore, provider::ApplicationContext};
use riglr_macros::tool;
use riglr_config::Config;
use std::sync::Arc;

// Define a simple tool using the #[tool] macro
#[tool]
async fn greeting_tool(
    name: Option<String>,
    context: &ApplicationContext,
) -> Result<serde_json::Value, ToolError> {
    let name = name.unwrap_or_else(|| "World".to_string());
    Ok(serde_json::json!({
        "message": format!("Hello, {}!", name),
        "timestamp": chrono::Utc::now()
    }))
}

// Set up ApplicationContext
let config = Config::from_env();
let context = ApplicationContext::from_config(&config);

// Set up worker with context
let worker = ToolWorker::<InMemoryIdempotencyStore>::new(
    ExecutionConfig::default(),
    context
);

// Register your tool
worker.register_tool(Arc::new(greeting_tool)).await;

// Create and process a job
let job = Job::new(
    "greeting_tool",
    &serde_json::json!({"name": "riglr"}),
    3 // max retries
)?;

let result = worker.process_job(job).await.unwrap();
println!("Result: {:?}", result);

§Architecture Patterns

§1. Unified Tool Architecture

All tools now use ApplicationContext for consistent access to resources:

use riglr_core::{ToolError, provider::ApplicationContext};
use riglr_macros::tool;
use std::sync::Arc;

// READ-ONLY OPERATIONS: Access RPC client from context
#[tool]
async fn get_sol_balance(
    address: String,
    context: &ApplicationContext,
) -> Result<serde_json::Value, ToolError> {
    // In practice, use concrete RPC client types from blockchain SDKs:
    // let rpc_client = context.get_extension::<Arc<MyRpcClient>>()
    //     .ok_or_else(|| ToolError::permanent_string("RPC client not available"))?;
     
    // Query balance using RPC client
    // ...
    Ok(serde_json::json!({ "balance_sol": 1.5 }))
}

// TRANSACTIONAL OPERATIONS: Use SignerContext within tools
#[tool]
async fn transfer_sol(
    recipient: String,
    amount: f64,
    context: &ApplicationContext,
) -> Result<serde_json::Value, ToolError> {
    // Access signer through SignerContext::current()
    // Perform transaction signing and submission
    // ...
    Ok(serde_json::json!({
        "transaction_hash": "ABC123",
        "amount": amount,
        "recipient": recipient
    }))
}
§2. Resilient Tool Execution

The ToolWorker provides automatic retry logic, timeouts, idempotency checking, and resource management:

  • Exponential backoff for failed operations
  • Configurable timeouts to prevent hanging operations
  • Idempotency store integration for safe retries
  • Resource limits to prevent system overload
  • Comprehensive metrics for monitoring
§3. Error Classification

The system distinguishes between different types of errors to enable intelligent retry logic:

  • Retriable errors: Network timeouts, rate limits, temporary service unavailability
  • Permanent errors: Invalid parameters, insufficient funds, authorization failures
  • System errors: Configuration issues, internal failures

§Features

  • redis - Enable Redis-backed job queue and idempotency store (default)
  • tokio - Async runtime support (required)
  • tracing - Structured logging and observability

§Production Considerations

For production deployments, consider:

  • Setting appropriate resource limits based on your infrastructure
  • Configuring Redis with persistence and clustering for reliability
  • Implementing proper monitoring and alerting on worker metrics
  • Using structured logging with correlation IDs for debugging
  • Setting up dead letter queues for failed job analysis

Re-exports§

pub use error::CoreError;
pub use error::ToolError;
pub use signer::SignerContext;
pub use signer::SignerError;
pub use signer::UnifiedSigner;
pub use idempotency::*;
pub use jobs::*;
pub use queue::*;
pub use tool::*;

Modules§

error
Error types and handling for riglr-core operations. Error types for riglr-core.
idempotency
Idempotency store implementations for ensuring operation uniqueness. Idempotency store for preventing duplicate execution of jobs.
jobs
Job definition and processing structures. Job data structures and types for task execution.
provider
Application context and RPC provider infrastructure. Chain-agnostic application context for dependency injection
provider_extensions
Extension traits for ergonomic client access. Extension traits for ApplicationContext to provide ergonomic access to chain-specific clients
queue
Queue implementations for distributed job processing. Job queue abstractions and implementations.
retry
Retry logic with exponential backoff for resilient operations. Generic retry utilities for robust async operations
sentiment
Sentiment analysis abstraction for news and social media content. Generic sentiment analysis abstraction
signer
Thread-safe signer context and transaction signing abstractions. Blockchain signer implementations and context management for secure transactions.
spawn
Task spawning utilities that preserve signer context across async boundaries.
tool
Core tool trait and execution infrastructure. Tool orchestration and execution framework.
util
Internal utility functions and helpers. Utility modules and functions for riglr-core

Structs§

AppConfig
Application configuration
Config
Main configuration structure that aggregates all subsystems
DatabaseConfig
Database configuration
FeaturesConfig
Feature flags configuration
NetworkConfig
Network configuration
ProvidersConfig
External API providers configuration

Enums§

Environment
Application environment