pub struct SubAgentSession<State: Send + Sync, Ctx: Send + Sync = ()> { /* private fields */ }Expand description
A persistent, reusable conversation with a single SubAgent.
Where SubAgentTool runs a fresh, stateless child run per tool call, a
SubAgentSession keeps the same underlying SubAgent (and therefore
the same AgentHarness) alive across multiple turns and retains the full
conversation transcript between them. This is post-completion reuse: the
child run finishes normally, the orchestrator inspects/awaits human input,
then calls the same sub-agent again — distinct from steering, which
interrupts a still-running agent.
§Human-in-the-loop reuse flow
sendthe first input (e.g. a user question). The session appends it to the retained transcript, runs the sub-agent over the full transcript, and folds the resulting assistant (and any tool) messages back in.- Inspect the returned [
AgentRun] and obtain human input out-of-band. - Wrap that human input as a
Message::userandsendit again. Because the prior turn’s messages are still in the transcript, the sub-agent answers with full context — without being killed and restarted.
Each send after the first emits AgentEvent::SubAgentReused
(alongside the usual SubAgentStarted/SubAgentCompleted
bracket) so reuse is observable in the event stream.
Implementations§
Source§impl<State: Send + Sync, Ctx: Send + Sync> SubAgentSession<State, Ctx>
impl<State: Send + Sync, Ctx: Send + Sync> SubAgentSession<State, Ctx>
Sourcepub fn new(subagent: Arc<SubAgent<State, Ctx>>) -> Self
pub fn new(subagent: Arc<SubAgent<State, Ctx>>) -> Self
Creates a session that reuses subagent across turns.
The child runs at depth 1 by default (caller parent_depth = 0); use
Self::with_parent_depth to express deeper nesting.
Sourcepub fn from_subagent(subagent: SubAgent<State, Ctx>) -> Self
pub fn from_subagent(subagent: SubAgent<State, Ctx>) -> Self
Creates a session from an owned SubAgent, wrapping it in an Arc.
Sourcepub fn with_events(self, events: EventSink) -> Self
pub fn with_events(self, events: EventSink) -> Self
Routes the reuse lifecycle and the child run’s own events onto events
so an external observer (or testkit recorder) sees every send. Returns
self for chaining.
Sourcepub fn with_parent_depth(self, parent_depth: usize) -> Self
pub fn with_parent_depth(self, parent_depth: usize) -> Self
Sets the caller depth the child runs at; the child run is created at
parent_depth + 1. Returns self for chaining.
Sourcepub fn subagent(&self) -> &Arc<SubAgent<State, Ctx>> ⓘ
pub fn subagent(&self) -> &Arc<SubAgent<State, Ctx>> ⓘ
Returns the reused sub-agent. The same Arc is shared across every
send, so this is how callers confirm the harness was never rebuilt.
Sourcepub fn transcript(&self) -> &[Message]
pub fn transcript(&self) -> &[Message]
Returns the accumulated conversation transcript carried across sends.
Sourcepub fn reset(&mut self)
pub fn reset(&mut self)
Clears the retained transcript and turn counter, so the next Self::send
starts a fresh conversation (re-seeding the fixed system prompt). The
underlying SubAgent/harness is left untouched and still reused.
Sourcepub async fn send(
&mut self,
state: &State,
ctx_data: Ctx,
input: Vec<Message>,
) -> Result<AgentRun>
pub async fn send( &mut self, state: &State, ctx_data: Ctx, input: Vec<Message>, ) -> Result<AgentRun>
Runs the reused sub-agent for one turn over the FULL accumulated transcript, then folds the produced assistant/tool messages back into the transcript so the next send continues with full context.
input (typically a single Message::user carrying human input) is
appended to the retained transcript before the run. On the first send
the sub-agent’s fixed SubAgent::with_system_prompt is prepended once.
The same underlying harness is reused on every call — nothing is
reconstructed.
§Errors
Returns TinyAgentsError::SubAgentDepth if the child depth would
exceed the configured max_depth, or any error surfaced by the child
agent loop.