Skip to content

Agent Orchestration

Orchestration is the single question of how you invoke a unit of work — a sub-agent, a system fetch, or an OOB LLM — and where its result goes. Every mechanism here writes its result to governed State under {name}:result (or {name}:error), so coordination is reactive and uniform: a Flow step completes on it via Guard::resolved(name), a watcher fires on it, or the next agent reads it — regardless of who produced it.

use gemini_adk_fluent_rs::prelude::*; // AgentMode, call_agent, Resolver
// Call — synchronous; the caller awaits. Use only for fast dependencies.
let verdict = call_agent("availability", agent, &state).await?; // → availability:result
// Dispatch — fire-and-forget; the conversation does not wait.
// Background — model-aware; runs detached, result delivered back to the model.
ModeSync?Lowers to
Callsync — caller awaitsagent run inline, result → State
Dispatchasync, fire-and-forgetBackgroundAgentDispatcher::dispatch
Backgroundasync, model-awarean agent-tool marked ToolExecutionMode::Background

A Resolver generalizes call from “a sub-agent” to any async source whose inputs come from State. It is the async sibling of the deterministic Recognizer:

use gemini_adk_rs::Resolver;
// A sub-agent (its String output becomes the result):
Resolver::agent("availability", availability_agent).resolve(&state).await?;
// Any async system — a tool call, HTTP fetch, or MCP request — bound from State:
Resolver::fetch("availability", |s: State| async move {
let slot = s.get::<String>("slot").unwrap_or_default();
Ok(serde_json::json!({ "open": slot == "afternoon" }))
}).resolve(&state).await?; // or .dispatch(state) to run detached
// A one-shot OOB LLM over a {key}-interpolated prompt:
Resolver::llm("summary", flash_llm, "Summarize the {topic} issue").resolve(&state).await?;

All three write {name}:result and record provenance under state_meta:{name}:result (source: agent | fetch | llm), readable with provenance(&state, "name:result").

A governed Flow drives orchestration in-session: a step’s on_enter runs a resolver/agent the moment it activates, and an Extract record can dispatch a downstream agent on_complete:

Live::builder()
.govern(booking_flow)
.on_step_enter("check", availability_agent, AgentMode::Call) // result → check:result
.extract_record(
Extract::record("triage")
.field("intent", Recognizer::one_of(["refund", "status"]))
.on_complete(router_agent, AgentMode::Dispatch) // result → triage:result
.build(),
)
.connect_from_env().await?;

Because every result lands in State under the same convention, the three lenses — extraction, orchestration, and flow — compose multiplicatively: extraction fills slots, a step orchestrates a sub-agent or fetch, and guards gate on either.