zeph_subagent/lib.rs
1// SPDX-FileCopyrightText: 2026 Andrei G <bug-ops>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4//! Subagent management: spawning, grants, transcripts, and lifecycle hooks.
5//!
6//! `zeph-subagent` provides the full lifecycle of sub-agent tasks within the Zeph agent
7//! framework. It covers:
8//!
9//! - **Definitions** ([`SubAgentDef`]) — parse YAML/TOML frontmatter from `.md` files,
10//! validate names and permissions, and load from priority-ordered directories.
11//! - **Manager** ([`SubAgentManager`]) — spawn, cancel, collect, and resume sub-agent tasks
12//! against a configurable concurrency limit.
13//! - **Grants** ([`PermissionGrants`]) — zero-trust TTL-bounded permission tracking for
14//! vault secrets and runtime tool grants.
15//! - **Hooks** ([`fire_hooks`]) — run shell commands at `PreToolUse`, `PostToolUse`,
16//! `SubagentStart`, and `SubagentStop` lifecycle events.
17//! - **Filter** ([`FilteredToolExecutor`]) — enforce per-agent [`ToolPolicy`] and denylist
18//! on every tool call before it reaches the real executor.
19//! - **Transcripts** ([`TranscriptWriter`], [`TranscriptReader`]) — persist conversation
20//! history to JSONL files for session resume and auditing.
21//! - **Memory** ([`ensure_memory_dir`], [`load_memory_content`]) — resolve and inject
22//! persistent `MEMORY.md` content into the sub-agent system prompt.
23//! - **Commands** ([`AgentCommand`], [`AgentsCommand`]) — typed parsers for `/agent` and
24//! `/agents` slash commands.
25//!
26//! # Quick start
27//!
28//! ```rust,no_run
29//! use std::sync::Arc;
30//! use zeph_subagent::{SubAgentDef, SubAgentManager};
31//!
32//! // Parse a definition from markdown frontmatter.
33//! let content = "---\nname: helper\ndescription: A helpful sub-agent\n---\nYou are a helper.\n";
34//! let def = SubAgentDef::parse(content).expect("valid definition");
35//! assert_eq!(def.name, "helper");
36//!
37//! // Create a manager with a concurrency limit of 4.
38//! let _manager = SubAgentManager::new(4);
39//! ```
40
41mod agent_loop;
42pub mod budget;
43pub mod command;
44pub mod cwd_guard;
45pub mod def;
46pub mod durable;
47pub mod error;
48pub mod filter;
49pub mod fleet;
50pub mod forward;
51pub mod grants;
52pub mod hooks;
53pub mod manager;
54pub mod memory;
55pub mod resolve;
56pub mod state;
57pub mod transcript;
58
59pub use budget::SessionSpawnBudget;
60pub use command::{AgentCommand, AgentsCommand};
61pub use cwd_guard::CwdLock;
62pub use def::{
63 MemoryScope, ModelSpec, PermissionMode, SkillFilter, SubAgentDef, SubAgentPermissions,
64 ToolPolicy, is_valid_agent_name,
65};
66pub use durable::{
67 DurableResolverSeat, SubagentResult, await_durable_subagent, make_durable_promise,
68 resolve_durable_promise, try_replay_durable_subagent,
69};
70pub use error::SubAgentError;
71pub use filter::{
72 FilteredToolExecutor, NetworkDenyToolExecutor, PlanModeExecutor, filter_skills,
73 normalize_tool_id,
74};
75pub use fleet::{FleetRegistry, FleetSessionInfo, FleetSessionStatus, SharedFleetRegistry};
76pub use forward::ForwardSurfaces;
77pub use grants::{Grant, GrantKind, GrantedSecret, PermissionGrants, SecretRequest};
78pub use hooks::{
79 HookAction, HookDef, HookError, HookMatcher, HookOutput, HookRunResult, McpDispatch,
80 PostToolUseHookInput, SubagentHooks, TOOL_ARGS_JSON_LIMIT, fire_hooks, hook_if_matches,
81 make_base_hook_env, matching_hooks,
82};
83pub use manager::{
84 SpawnContext, SpawnOrigin, SubAgentHandle, SubAgentManager, SubAgentStatus,
85 intersect_allowlists,
86};
87pub use memory::{ensure_memory_dir, load_memory_content};
88pub use resolve::resolve_agent_paths;
89pub use state::SubAgentState;
90pub use transcript::{TranscriptMeta, TranscriptReader, TranscriptWriter, sweep_old_transcripts};
91/// Async callback type for spawning an external ACP sub-agent by shell command.
92///
93/// Returns the sub-agent's text output on success or an error string on failure.
94/// Installed via `AgentBuilder::with_acp_subagent_spawn_fn` when the `acp` feature is enabled.
95pub type AcpSubagentSpawnFn = std::sync::Arc<
96 dyn Fn(
97 String,
98 ) -> std::pin::Pin<
99 Box<dyn std::future::Future<Output = Result<String, String>> + Send + 'static>,
100 > + Send
101 + Sync,
102>;