Skip to main content

Crate behest

Crate behest 

Source
Expand description

Building blocks for Rust-native AI agent runtimes.

§Architecture

behest has two complementary surfaces:

The invocation surface — a Socket.IO-inspired emit / on model for interacting with an agent. Emit a user message, receive streaming events back through typed handlers. This is the caller-facing API, built on RuntimeInvocation.

The assembly surface — pluggable components (providers, tools, stores, transports) wired together via ComponentRegistry and driven by a coordinated lifecycle. This is the operator-facing API for composing a runtime from parts, built on ManagedRuntime.

                  emit("question")       on(TextDelta, handler)
  Caller ──────────►  RuntimeInvocation  ──────────►  Caller
                         │
                         ▼
                   AgentRuntime  ◄──  ComponentRegistry
                         │              │
                         ▼              ▼
                run_loop (FSM)      provider / tool / store / transport

The two surfaces are independent: you can use RuntimeInvocation with a hand-assembled AgentRuntime, or drive the ManagedRuntime lifecycle from your own invocation layer. They meet at AgentRuntime — the shared kernel that both paths produce.

§Quick start

use behest::prelude::*;
use behest::runtime::RuntimeInvocation;

// 1. Build config & runtime
let config = AgentConfigBuilder::default()
    .with_env("BEHEST")?
    .with_provider(ProviderId::new("openai"), ProviderConfig::new("https://api.openai.com/v1")
        .with_provider_type(ProviderType::OpenAi)
        .with_api_key("env:OPENAI_API_KEY")
        .with_model("gpt-4o"))
    .build()?;
let runtime = Arc::new(config.into_runtime().await?);

// 2. Wrap in the invocation facade
let inv = RuntimeInvocation::new(runtime);

// 3. Subscribe to text deltas
let handle = inv.on(EventKind::TextDelta, |envelope, _session, _control| async move {
    if let AgentEvent::TextDelta(td) = &envelope.event {
        print!("{}", td.delta);
    }
}).await?;

// 4. Emit a request
let output = inv.emit(|_session, _control| async move {
    EmitRequest::new(provider_id, model, "Hello, world!")
}).await?;

drop(handle);

§Modules

  • runtime: Runtime kernel, invocation facade, component system, policy
  • provider: Provider traits, request/response types, and registry
  • tool: Tool trait, registry, scoping
  • context: Multi-adapter context factory for composing chat requests
  • store: Persistence traits and backends for sessions, embeddings, artifacts
  • config: Centralized configuration with file, env, and builder support
  • adapt: Concrete provider adapters (OpenAI, Anthropic)
  • error: Error types and result aliases
  • rag: Retrieval-Augmented Generation context adapter (feature = rag)
  • queue: External event publishing to message brokers (feature = queue)

Re-exports§

pub use crate::error::ContextError;
pub use crate::error::Error;
pub use crate::error::ProviderError;
pub use crate::error::Result;
pub use crate::error::StorageError;
pub use crate::error::ToolError;
pub use crate::health::HealthStatus;
pub use crate::runtime::AgentEvent;
pub use crate::runtime::AgentRuntime;
pub use crate::runtime::AnyComponent;
pub use crate::runtime::AnyComponentError;
pub use crate::runtime::CompactionResult;
pub use crate::runtime::CompactionService;
pub use crate::runtime::Component;
pub use crate::runtime::ComponentContext;
pub use crate::runtime::ComponentDescriptor;
pub use crate::runtime::ComponentError;
pub use crate::runtime::ComponentFactory;
pub use crate::runtime::ComponentRegistry;
pub use crate::runtime::ComponentState;
pub use crate::runtime::ContextPipelineComponent;
pub use crate::runtime::ContextPipelineConfig;
pub use crate::runtime::Control;
pub use crate::runtime::EmitRequest;
pub use crate::runtime::EventKind;
pub use crate::runtime::ExtensionError;
pub use crate::runtime::ExtensionPoint;
pub use crate::runtime::Extensions;
pub use crate::runtime::FactoryError;
pub use crate::runtime::FactoryFn;
pub use crate::runtime::FactoryRegistry;
pub use crate::runtime::FileSessionDataStore;
pub use crate::runtime::FileSnapshotStore;
pub use crate::runtime::InvocationError;
pub use crate::runtime::InvocationEvent;
pub use crate::runtime::InvocationHandle;
pub use crate::runtime::InvocationSession;
pub use crate::runtime::ManagedError;
pub use crate::runtime::ManagedRuntime;
pub use crate::runtime::MemoryArtifactStoreComponent;
pub use crate::runtime::MemoryEmbeddingStoreComponent;
pub use crate::runtime::MemoryExecutionStoreComponent;
pub use crate::runtime::MemoryRunStoreComponent;
pub use crate::runtime::MemorySessionDataStore;
pub use crate::runtime::MemorySessionStoreComponent;
pub use crate::runtime::ModelRouter;
pub use crate::runtime::ProviderHttpComponentConfig;
pub use crate::runtime::RegistryError;
pub use crate::runtime::RunId;
pub use crate::runtime::RunOutput;
pub use crate::runtime::RunRequest;
pub use crate::runtime::RunStatus;
pub use crate::runtime::RuntimeError;
pub use crate::runtime::RuntimeEventBridge;
pub use crate::runtime::RuntimeEventBridgeError;
pub use crate::runtime::RuntimeEventBridgeHandle;
pub use crate::runtime::RuntimeEventEnvelope;
pub use crate::runtime::RuntimeEventId;
pub use crate::runtime::RuntimeEventStore;
pub use crate::runtime::RuntimeEventStoreError;
pub use crate::runtime::RuntimeInvocation;
pub use crate::runtime::RuntimePolicy;
pub use crate::runtime::RuntimeRoom;
pub use crate::runtime::RuntimeStreamAdapter;
pub use crate::runtime::RuntimeStreamError;
pub use crate::runtime::RuntimeSubscription;
pub use crate::runtime::RuntimeSubscriptionError;
pub use crate::runtime::RuntimeSubscriptionHub;
pub use crate::runtime::SessionDataError;
pub use crate::runtime::SessionDataStore;
pub use crate::runtime::ShutdownToken;
pub use crate::runtime::Snapshot;
pub use crate::runtime::SnapshotStore;
pub use crate::runtime::TypedAnyComponent;
pub use crate::runtime::TypedFactory;
pub use crate::runtime::default_factory_registry;
pub use crate::runtime::register_context_pipeline;
pub use crate::runtime::register_memory_stores;
pub use crate::runtime::register_providers;
pub use crate::runtime::OpenAiChatComponent;
pub use crate::runtime::OpenAiEmbeddingComponent;
pub use crate::runtime::AnthropicChatComponent;
pub use crate::tool_output::ToolOutputConfig;
pub use crate::tool_output::TruncationResult;
pub use crate::runtime::RedisSessionDataStore;

Modules§

adapt
Concrete provider adapters for model vendors.
agent
Agent definition and registry.
config
Centralized agent configuration.
context
Context construction and multi-adapter composition.
error
Error types shared across the public API.
health
Health status primitives shared by every Component.
prelude
Convenient imports for application and integration code.
provider
Provider-neutral contracts for chat, tools, streaming, and embeddings.
queue
External event publishing for agent observability.
rag
Retrieval-Augmented Generation (RAG) context adapter.
runtime
Agent runtime kernel.
store
Persistence layer for sessions, embeddings, artifacts, and executions.
token
Token estimation using character-based heuristics.
tool
Runtime tool registry and execution primitives.
tool_output
Tool output truncation with head+tail sampling.
tool_scope
LIFO scoped tool registry with shadow-stack semantics.