Skip to main content

agentd/
lib.rs

1// SPDX-License-Identifier: AGPL-3.0-only
2//! agentd — a minimal, MCP-native, reactive agent runtime.
3//!
4//! One binary that is CLI, daemon, and subagent re-exec. A **supervisor**
5//! owns lifecycle, triggers, and the process tree but never reasons; the
6//! **agentic loop** lives only inside subagent processes. Tools come only
7//! from MCP servers; reactivity comes from MCP resource subscriptions;
8//! agentd is itself an MCP server so agents compose with one protocol.
9//!
10//! The split is deliberate: because only subagent processes reason, a wedged
11//! or runaway model can never take the supervisor down with it, and the
12//! supervisor's kill/reap/budget guarantees hold no matter what a model does.
13//!
14//! Module map below. `agentloop` is named to avoid the `loop` keyword.
15
16pub mod a2a; // A2A surface: principals/roles/authorization + durable tasks
17#[cfg(feature = "aauth")]
18pub mod aauth; // agent-side AAuth signing for AAuth-protected MCP endpoints
19pub mod agentloop; // the in-child ReAct loop + terminal-status state machine
20pub mod auth; // endpoint credential providers + durable token cache: OAuth, AWS SigV4, SPIFFE
21pub mod cel; // CEL expression seam (feature `cel`; always compiled, fail-closed without it)
22pub mod config; // precedence (built-in<file<env<flag) + validate-at-startup; config::{file,yaml,paths,watch}
23pub mod context; // durable transcripts, plan, memory, compaction, skills
24pub mod engine; // workflow engine: graph model, templates, durable runs + scheduler
25pub mod exit; // the public exit-code table + terminal-status -> code map
26pub mod governor; // token governor: windowed durable budgets + shedding tactics
27pub mod identity; // instance identity from the Kubernetes downward API (env-only)
28pub mod intel; // intelligence client + provider adapters
29pub mod jsonschema; // dependency-free JSON Schema subset validator (tool contracts, workflow schemas)
30// JSON-RPC 2.0 codec + framing lives in the reusable `mcp` crate; re-exported
31// so `crate::json::*` resolves (MCP + the supervisor<->subagent channel).
32pub use ::mcp::rpc as json;
33pub mod mcp; // MCP client (to servers) + self-MCP server + registry/config
34// Transport primitives live in the reusable `net` crate; re-exported so
35// `crate::net::*` resolves across the runtime (MCP transport + intelligence).
36pub use ::net;
37pub mod obs; // logging, health, tracing, metrics
38pub mod registry; // tool registry: internal > code > MCP, contracts, overrides, grants
39pub mod runtime; // the runtime: event loop, turn workers, lifecycle
40pub mod sec; // secrets, tool-scope, gated exec
41pub mod sha; // dependency-free SHA-256 (content identity: workflow hashes, skill bodies, artifacts)
42pub mod signals; // sigaction + self-pipe wakeup; SIGTERM/INT/CHLD/PIPE/HUP latches
43pub mod state; // durable state model: entities, manifest, inbox, timers, restore
44pub mod store; // remote state store adapters: a 4-op contract over MCP tools / HTTP / memory
45pub mod subagent; // supervisor<->subagent control protocol
46pub mod supervisor; // the reactor, process tree, spawn/reap/liveness/kill/restart
47pub mod tools; // CODE-REGISTERED tools — the embedder seam
48pub mod triggers; // execution modes + reactive routing + timers
49pub mod wire; // MCP + intelligence wire types
50
51/// Crate version, surfaced in logs (`agentd_build_info`) and `--version`.
52pub const VERSION: &str = env!("CARGO_PKG_VERSION");
53
54/// Announce a bound loopback listener's address through `addr_file` — the
55/// discovery handshake for the built-in test mocks (`--internal-mock-llm`,
56/// `--internal-mock-mcp-http`): the harness passes a fresh path, waits for the
57/// file to exist, then reads `host:port` from it. Written atomically (tmp +
58/// rename) so a waiter never observes a half-written address.
59pub fn announce_addr(addr_file: &str, listener: &std::net::TcpListener) -> std::io::Result<()> {
60    let addr = listener.local_addr()?;
61    let tmp = format!("{addr_file}.tmp");
62    std::fs::write(&tmp, addr.to_string())?;
63    std::fs::rename(&tmp, addr_file)
64}