leviath_runtime/lib.rs
1//! # Leviath Runtime
2//!
3//! ECS-based agent execution engine using bevy_ecs.
4//!
5//! The runtime manages agent lifecycle, context window management, task scheduling,
6//! and inference execution through a game-loop-inspired architecture where agents
7//! are entities and their behaviors are systems.
8//!
9//! ## Embedding
10//!
11//! [`AgentWorld`] is the front door for running agents inside your own
12//! application - no `lev` CLI, daemon, or config file. Build a world from
13//! plain values, spawn an agent, and drive the event stream:
14//!
15//! ```no_run
16//! use leviath_runtime::{AgentWorld, BlueprintSource, ProviderCreds, SpawnSpec, WorldEvent};
17//!
18//! # async fn embed() -> Result<(), Box<dyn std::error::Error>> {
19//! let world = AgentWorld::builder()
20//! .provider(ProviderCreds {
21//! name: "anthropic".to_string(),
22//! api_key: std::env::var("ANTHROPIC_API_KEY").ok(),
23//! ..ProviderCreds::simple("anthropic")
24//! })
25//! .build()?;
26//!
27//! let mut events = world.events();
28//! let run = world
29//! .spawn(SpawnSpec::new(
30//! BlueprintSource::Path("coder.leviath".into()),
31//! "Build a CSV parser",
32//! std::env::current_dir()?,
33//! ))
34//! .await?;
35//!
36//! while let Some(event) = events.next().await {
37//! match event {
38//! WorldEvent::StageTransition { from, to, .. } => println!("{from} -> {to}"),
39//! WorldEvent::ToolCallStarted { tool, .. } => println!("running {tool}"),
40//! WorldEvent::Interaction { request, .. } => {
41//! // The agent asked a question: answer via world.answer(...).
42//! }
43//! WorldEvent::Completed { run_id, status, .. } if run_id == run.as_ref() => break,
44//! _ => {}
45//! }
46//! }
47//! world.shutdown().await;
48//! # Ok(())
49//! # }
50//! ```
51//!
52//! ## Stability layers
53//!
54//! - [`AgentWorld`] and the other [`embed`] types are the stable embedding
55//! surface.
56//! - [`WorldHost`] and [`PipelineWorld`] are the semi-stable machinery both
57//! the daemon and `AgentWorld` are built on; use them when you need your
58//! own assembly (custom spawners, hooks, tick control).
59//! - The raw ECS underneath ([`PipelineWorld::world_mut`]) is the unstable
60//! escape hatch: it tracks this crate's `bevy_ecs` version (re-exported as
61//! [`ecs`]) and carries no compatibility promise.
62
63// Public because [`tool_bridge::ToolJob`] carries a `CancelToken`, so anything
64// handing work to the tool lane needs to name the type.
65pub mod cancel;
66pub(crate) mod compaction_bridge;
67pub mod components;
68pub mod context_setup;
69pub(crate) mod context_tools;
70pub(crate) mod context_transform;
71#[cfg(feature = "control-socket")]
72pub mod control_socket;
73pub mod custom_region;
74pub mod dynamic_interaction;
75pub mod embed;
76pub mod fanout;
77pub(crate) mod gate_prompt;
78pub mod host;
79pub(crate) mod inference_bridge;
80pub mod inference_pool;
81pub mod interaction_hub;
82pub mod interaction_points;
83pub(crate) mod lane_supervisor;
84pub mod persistence;
85pub(crate) mod persistence_bridge;
86pub mod pipeline;
87pub mod provider_creds;
88pub(crate) mod providers;
89pub(crate) mod repetition;
90pub mod restore;
91pub mod script_provider;
92pub mod taint;
93pub mod telemetry;
94pub(crate) mod tick_scope;
95pub mod title;
96pub(crate) mod title_bridge;
97pub mod tool_bridge;
98pub mod world;
99// test_support.rs gates itself with an inner `#![cfg(test)]` attribute, so no
100// `#[cfg(test)]` is needed here (adding one would trigger clippy's
101// `duplicated_attributes` lint under `-D warnings`).
102mod test_support;
103
104pub use components::{AgentState, AgentStatus, ContextWindow, ParentRef, SubAgentChildren};
105pub use embed::{
106 AgentWorld, AgentWorldBuilder, BasicToolService, BlueprintSource, EmbedError, EventStream,
107 RunId, SpawnSpec,
108};
109pub use fanout::{FanOutSpawner, FanOutSpawnerRes};
110pub use host::{ControlOp, SpawnArgs, WorldEvent, WorldHost};
111pub use inference_bridge::RetryPolicy;
112pub use inference_pool::{InferencePoolConfig, InferencePools};
113pub use interaction_hub::InteractionHub;
114pub use pipeline::{ModelDefaults, ResolvedStage, ToolService};
115pub use provider_creds::{ProviderCreds, build_provider_registry};
116pub use providers::ProviderRegistry;
117pub use taint::TaintGate;
118pub use tool_bridge::BoxedToolExec;
119pub use world::{PipelineWorld, TickOutcome};
120
121/// The name issue-facing docs use for the world's event enum; the same type
122/// as [`WorldEvent`].
123pub type AgentEvent = WorldEvent;
124
125/// The `bevy_ecs` version this runtime is built against, for code that
126/// reaches through [`PipelineWorld::world_mut`] into the raw ECS. Depending
127/// on this re-export (instead of your own `bevy_ecs`) keeps the versions
128/// aligned.
129pub use bevy_ecs as ecs;