Expand description
P5-6 (COMPOSABLE-HARNESS-DESIGN.md §2 module 4 tools.background: “D1
background exec + monitor/event feed; D10 bg-manager; D3 self-paced/
scheduled loops”; §2.1 “tools.background → permissions.approvals
(auto-policy) [C6 as dep]”; §2.2 C6): the pure, agent-independent data
shapes and bounded-buffer arithmetic a runtime agent’s
background_exec/background_status/background_list/background_kill
intrinsics build on — kept separate from agent.rs so the bounded-
capture truncation logic and job-id shape are unit-testable without a
full Agent/mock-Provider/real-subprocess harness, the same
“pure config → set, testable without the loop” precedent
subagent runtime documents for itself (P5-3).
Activation. Everything here is inert until Agent actually consults
it, which only happens when Config::tools_background_enabled is true
(capabilities.tools_background.enabled, default false) — importing
this module changes nothing for an agent that never turns the module on.
Process-kill reuse. The actual OS-process spawn/kill machinery lives
in the agent loop (it needs tokio::process::Command/Child, which this
module deliberately does not depend on, keeping it synchronous and
trivially unit-testable). The concurrency bound reuses
the subagent concurrency guard verbatim — the same
generic Arc<AtomicUsize> gauge machinery, just a second, independent
gauge instance scoped to background JOBS rather than subagent SPAWNS
(Agent::background_concurrency_gauge, distinct from
Agent::subagent_concurrency_gauge).
Structs§
- Captured
Output - Bounded, incrementally-appended output capture shared (via
Arc) between a job’s stdout/stderr reader tasks and whatever later polls it (background_status/background_list). Thread-safe; every method is fail-soft on a poisoned lock (treats it as “temporarily unavailable”, the same posturecrate::permissions::approval::ApprovalCachealready documents for itself) rather than panicking a reader task or a tool call.
Enums§
- JobStatus
- A background job’s run state, as observed by
background_status/background_list.
Constants§
- DEFAULT_
MAX_ CONCURRENT - P5-6 (resource bound, mirroring
crate::subagents’s “max concurrent… cap, fail-closed… configurable” precedent): the default maximum number of background jobs this agent may have in flight at once. - DEFAULT_
MAX_ OUTPUT_ BYTES - P5-6 (build brief “cap the buffer like P5-2’s 16MiB caps”): the default
per-job bounded-capture ceiling, matching
crate::mcp::MCP_MAX_RESPONSE_BYTES’s hardening precedent — generous for real command output while bounding how much memory one background job (let alonemax_concurrentof them at once) can force this process to hold.
Functions§
- next_
job_ id - A fresh, process-unique background job id (
"bg-<hex-ts>-<hex-seq>"), given the caller’s own millisecond timestamp (kept as a parameter rather than reading the clock in here, so this stays a pure function for the unit tests below).