Arrow keys choose a result, Enter opens it, Escape closes. Press / on any page to search.
Compare
A pure ADK agent beside an Antigravity SDK agent, part by part: what comes built in, what you switch on, what you write. The depth control in the header adds parts and detail.
Parts of an agent
Keyboard
Tab reaches every link. The address of a part is #/compare/part-id. The row is highlighted and scrolled into view, and a part deeper than the current depth raises it.
Decide
Which one should I use? A few questions in turn end in an answer. The answer names what to use and says why in one sentence. It links to the comparison it rests on and the box on the map.
The answers you give stay above the next question, and you can change them. The address keeps them, so a link opens the guide where you left it. The depth control in the header sets which guides show and how much each answer says.
Keyboard
Tab reaches each question. The arrow keys move between its options and choose one, and the next question or the answer appears below it. A guide's address is #/decide/guide-id&a=1.2: the numbers are the options chosen, in order.
Disciplines
The names people give to the work around an agent, from writing one instruction to wiring many runs into a structure. For each name: what it means, who said so and when, and which parts of ADK and the Antigravity SDK it works on. The depth control sets how much of each entry is shown.
Five names, each for a larger unit of work than the one inside it, the unit as the sources state it. Which name contains which is argued (harness and context swap places in several sources). The nesting here is the one that most sources give, and every entry below says where its sources disagree.
Prompt engineering: one instruction. Levers: instruction, static_instruction, description. In the SDK: system_instructions.
Context engineering: one model call. Levers: Session, State, memory, compaction, caching, mode="task". In the SDK: save_dir.
Harness engineering: one agent run. Levers: Runner, App, tools, callbacks, plugins, code executors, evals. The SDK is a harness.
Loop engineering: recurring runs. Levers: trigger endpoints, max_llm_calls, RetryConfig, resumability. In the SDK: schedule, BudgetConfig, StopHook.
Graph engineering: loops wired into a structure. Levers: Workflow, routes, JoinNode, parallel workers, ctx.run_node.
What the status says
Looked for and not found
Searched on across the sources above and the web, for three things. The first was "workflow engineering", "orchestration engineering" and "tool engineering" as named disciplines (vendor pages only, none with a definition). The second was a coiner for "intent engineering" (two unrelated definitions exist). The third was "loop engineer" as a job title. The sites adk.dev and antigravity.google use none of the five names on the ladder. The one phrase of the kind on antigravity.google is "agentic engineering platform".
Keyboard
Tab reaches every link. The address of an entry is #/disciplines/entry-id. The section is scrolled into view, and an entry deeper than the current depth raises it.
Flows
What happens, in order. Step through each figure with the buttons or the arrow keys. The caption under the figure changes with the step, and the step list below is the same text in full.
Four more flows, the internals (one model call, one Live session, a call through Agent Gateway, a turn of an AntigravityAgent), show at L300.
The event loop L100
Nothing in ADK runs to completion in one go. The agent is an async generator that yields an event and pauses. The Runner records that event, applies its side effects and only then lets the agent continue. Every flow on this page that runs an agent or a graph happens inside this loop (one invocation, the hook order, state, a graph run, a graph's pause and resume, and at L300 a model call, a Live session and an AntigravityAgent turn). The deployment path and the gateway call show what is around the loop.
OverviewStep through the mechanism with the buttons or the arrow keys.
A user message arrives. The Runner loads the session through the SessionService and appends the message as the first event of this invocation.
The Runner calls the agent's run_async with an InvocationContext: the session, its state, the services, the invocation id.
The agent works (callbacks, a model call, maybe a tool) until it has something to say, then yields an Event. The generator pauses right there.
The Runner commits the event: it appends the event to the session and applies the state_delta of the event through the SessionService. A file that a tool saved is already in the ArtifactService. The artifact_delta of the event records only its version.
The committed event is forwarded upstream. A streaming client sees the event now. Partial (streaming) events are forwarded but not committed.
The Runner lets the agent resume after its yield. From here on, the state the agent reads is the committed state.
Yield, commit, forward, resume: the loop repeats until the agent yields its final response, which the client recognises with is_final_response().
One call to run_async with one new message is an invocation. This is the common shape: the model asks for a tool, the tool runs, the model answers. Dashed arrows are returns, and every yield is a pause. Every committed event is also streamed to the client, but only the last one is drawn.
OverviewStep through the mechanism with the buttons or the arrow keys.
The client calls run_async with the user id, the session id and the new message. One such call is one invocation.
The Runner loads the session from the SessionService and appends the user message as the invocation's first event.
The Runner builds an InvocationContext (session, state, services, invocation id) and calls the agent's run_async.
The agent sends its instruction, the conversation history and the declarations of its tools to the model. The model answers with a function call.
The agent yields the function-call event and pauses. The Runner appends it to the session before anything else happens, and forwards it to the client.
The agent runs the tool. Through tool_context the tool can read and write state, save artifacts or ask for confirmation. It returns a dictionary. Since ADK 2.11, the client can stop the run here. When the abort_signal that the client passed is set, the Runner answers a call still open with an abort error. The Runner appends the error to the session and ends the stream.
The agent yields the function response as an event with a state_delta. The Runner appends the event, applies the delta through the SessionService and forwards the event to the client.
The model receives the tool result with the history and writes the answer.
The agent yields the final text as an event with is_final_response() true. The Runner streams the event to the client like every committed event, and the invocation ends.
Two families of hooks wrap a run: plugins, registered once and global, and callbacks, set per agent. They fire in a fixed order at fixed stages; for every stage they share, the plugin's hook runs before the agent's callback. Returning None continues; returning a value replaces the step.
OverviewStep through the mechanism with the buttons or the arrow keys.
The user message arrives. A plugin's on_user_message runs first and may rewrite or reject it; there is no agent callback at this stage.
The Runner starts the run: before_run on every plugin. Plugins are registered once on the App and see every agent in the tree.
The agent starts. For every hook pair the plugin's hook runs first, then the agent's own callback: before_agent, then before_agent_callback. Returning None continues; returning Content skips the agent and uses that content instead. A plugin that returns a value ends the round: later plugins and the agent's callback do not run.
Around the model call: before_model (plugin), before_model_callback (agent), the call, after_model (plugin), after_model_callback (agent). A before hook that returns an LlmResponse skips the model, which is how guardrails and caches work. If the call fails, on_model_error (plugin) and then on_model_error_callback (agent) run; an LlmResponse returned by either stands in for the failed call.
Around each tool call: before_tool (plugin), before_tool_callback (agent), the tool, after_tool (plugin), after_tool_callback (agent). A before hook returning a dict skips the tool and uses the dict as its result. If the tool raises, on_tool_error (plugin) and then on_tool_error_callback (agent) run; a dict returned by either becomes the tool's result. Since ADK 2.13 both also run when the call is cancelled, with the asyncio.CancelledError, so that they can release what a before hook set up; the cancellation goes on whatever they return.
Each yielded event passes through the plugins' on_event as the Runner commits it; it can be observed or modified before it reaches the client.
The agent finishes: after_agent (plugin) and after_agent_callback (agent); returning Content replaces the agent's final output. If the agent raised, on_agent_error runs on every plugin; it only observes, and the error is raised again.
The run ends: after_run on every plugin, or on_run_error if the run raised, which again only observes. Order of precedence for the whole picture: plugins first, then the agent's callbacks, at every stage they share.
Where a write goes: state, memory and artifacts L200
Every write lands in one store, and the store decides how long it lasts. State is written as deltas and committed by the Runner, and a key's prefix decides how far it reaches; memory and artifacts are written by explicit calls and outlive the conversation.
OverviewStep through the mechanism with the buttons or the arrow keys.
Inside a tool or callback, writing ctx.state["booking_step"] = 2 changes the session's state at once, so later code in this invocation already reads 2, and it records the change as state_delta on the event the agent will yield. Since ADK 2.13 a write into a dict or list read from state, ctx.state["prefs"]["lang"] = "sk", is recorded too, unless the container has no JSON form. Nothing is stored yet.
When the agent yields that event, the Runner calls the SessionService's append_event, which applies state_delta and stores the event. From here on the stored session carries booking_step = 2; if the run fails before the commit, the write is lost.
The SessionService persists the session: a SQLite file in the agent's .adk folder with adk web, process memory in tests and InMemoryRunner, a database, or Agent Platform Sessions in production. A plain key belongs to this session only.
A key written as user:preferred_language is shared by every session of that user in this app; the session service keeps it outside any one session.
An app: key is shared by every user of the app, which suits counters and feature flags. Use it sparingly; it is global.
A temp: key lives only until the invocation ends and is never persisted, which is right for intermediate results between steps.
An agent with output_key="booking_step" puts its final text into the state_delta of its last event, so it reaches state like any other write, and the next agent's instruction reads it back with {booking_step}.
Memory is never written by itself: your code calls add_session_to_memory (from an after_agent_callback, say) and Memory Bank turns the session into memories. In a later session, preload_memory puts the relevant ones into the next model request, not into state; load_memory is a tool the model calls.
Files are not state: save_artifact writes a versioned file to the artifact service when it is called, not on commit (Cloud Storage in production); a user: prefix on the name keeps it across sessions.
How a graph Workflow runs: a loop, a fan-out, a join L200
A Workflow runs its graph by triggers, not by the order of its edge list: a node runs when an edge triggers it, from START or from a node that has finished, and what travels along that edge is its node_input. The figure draws two of the example's graphs from support_desk/workflow.py, run as the example's tests run them, offline on a scripted model: steps 1 to 7 are one run of refinement_loop, a pipeline that a routed edge closes into a loop, and steps 8 and 9 one run of enrichment_workflow, a fan-out gathered by a JoinNode.
OverviewStep through the mechanism with the buttons or the arrow keys.
The client calls run_async with the customer's message. The Runner appends it to the session and runs the root, refinement_loop, with the message as its node_input. The workflow triggers every node an edge from START leads to, here new_round, with that input.
new_round returns Event(output=node_input, state={"rounds": 0, "draft": "", "review": ""}). The event goes to the Runner, which appends it to the session, applying the state delta, and yields it to the client; until then the node waits. Every event of every node takes this way, so the session holds the run in the order it happened.
The edge from new_round to loop_drafter has no route, so it is always followed: new_round's output, the message, is loop_drafter's node_input. An LlmAgent in a graph runs single_turn unless its mode says otherwise, even one with sub_agents (only an agent reached as another's sub-agent runs chat): that input is its user turn, and nothing said before it is in the request. It calls lookup_order, then answers; output_key="draft" puts the answer in state, and the answer is also the node's output.
loop_reviewer gets the draft twice: as its node_input, which is its user turn, and from state, where {draft} in its instruction reads it. Its verdict, here a correction rather than PASS, goes to state under review.
review_gate, a custom agent with no model, reads review and rounds from state, counts the round and yields Event(state={"rounds": 1}, route="revise"). When a node finishes, the workflow follows its edges without a route and those whose route matches, a DEFAULT_ROUTE edge when none does: here only the edge back to loop_drafter. The cycle passed validation only because that edge has a route, and the workflow counts no rounds; the gate does, up to MAX_ROUNDS = 3.
loop_drafter runs again, as loop_drafter@2. The gate emitted no output, so this run has no node_input. Since ADK 2.12 a single_turn node sees only the events of its own run and those outside any node, so the reviewer's reply is not in the request: the drafter's turn is the customer's message again, and {draft?} brings the first draft in from state. The review reaches the drafter only through state, where {review?} in its instruction reads it. loop_reviewer gets the new draft as before and answers PASS.
review_gate finds PASS and routes "done". accept(draft) is called with the draft from state, read by its parameter's name. accept has no outgoing edge, so it is a terminal node and its output is the workflow's output. With no node running and none triggered, the run ends.
Another run, of enrichment_workflow. START has two edges, so fetch_order and fetch_history are both triggered with the same input and start together, each as an asyncio task of its own; the workflow handles whichever finishes first. max_concurrency, unset here, would cap how many nodes run at once.
merge is a JoinNode: a predecessor's trigger does nothing until every node with an edge into merge has finished; then merge runs once and hands on a dict of their outputs keyed by node name, from which summarize makes the workflow's output. An ordinary node with two predecessors would run twice instead, once with each output. Since ADK 2.13 a JoinNode inside a loop waits again on every round: only the runs finished since it last fired count.
A graph run that pauses for a person and resumes L200
A node that needs a person yields RequestInput, and the graph stops there: the call to run_async ends with the request in the session, and nothing runs until the person answers. The answer comes in a second call, which resumes the same invocation: the workflow runs again from START, skips what finished, and the waiting node takes the answer. The figure draws adk-python's request_input sample, run offline on a scripted model: steps 1 to 5 are the first call, 6 to 8 the second, and step 9 the setting that makes the waiting node run again.
OverviewStep through the mechanism with the buttons or the arrow keys.
The client calls run_async with the customer's complaint. The Runner appends it to the session and runs the root, request_input, with the message as its node_input, and the workflow triggers process_input from START. Up to the pause this is an ordinary graph run.
process_input puts the complaint and an empty feedback in state; draft_email, an LlmAgent node, writes a reply, which output_key="draft" puts in state as well. Each event goes through the Runner into the session before its node goes on, as in any graph run.
request_human_review(draft), a function node that reads the draft from state by its parameter's name, yields RequestInput(message=…). The node turns it into an event: a function call named adk_request_input whose arguments are the RequestInput's fields and whose id is the interrupt id, a new UUID unless interrupt_id is given; the id is also listed in long_running_tool_ids. The workflow records it as the node's interrupt, and the Runner appends the event.
When the node's run ends, the workflow finds the interrupt: the node is WAITING and no edge out of it is followed, so handle_human_review does not run. What the function does after the yield still runs now, but an output it gives reaches no node. With nothing else to run, the workflow ends with the interrupt id instead of an output, and run_async ends without an error. The client has the request, an event whose is_final_response() is true because it is long-running.
Between the two calls nothing runs: what the resume needs is in the session. Its events hold the message, the events of process_input and draft_email, and the request; state holds complaint, feedback and draft. With ResumabilityConfig(is_resumable=True) on the App, the workflow also appends a checkpoint event with the status of each node so far whenever a node starts, ends or waits, the last with request_human_review WAITING on its interrupt id; ADK 2.14 does not read them back.
The person answers, and the client calls run_async again with a FunctionResponse named adk_request_input, its id the interrupt id and its response {"result": "approve"}. The Runner finds the call that id belongs to and resumes that invocation, under the same invocation id; a graph at the root needs no ResumabilityConfig for this. It appends the response and runs the workflow again with the first message as node_input. Plain text would start a new invocation, which runs the graph from START; text and a response in one message raise ValueError.
The workflow does not resume from a snapshot: it starts again from START and rebuilds each node's state from this invocation's events in the session. process_input and draft_email finished, so they are skipped: the model is not called again and the state write is not repeated. request_human_review has an interrupt that the response answers, and with rerun_on_resume=False, a function node's default, it does not run either: the answer, unwrapped from {"result": …}, is its output.
handle_human_review gets "approve" as its node_input and routes "approved": send_email yields its message, and the run ends as any graph run does. "reject" would route to reject_email. Any other answer is feedback: it goes to state, the route "revise" runs draft_email again as draft_email@2, and request_human_review@2 pauses with a new interrupt id, for a third call to answer in the same invocation.
A node with rerun_on_resume=True runs again on resume instead, from its start, and finds the answer in ctx.resume_inputs under the interrupt id. An LlmAgent node and a tool node have it by default; a function gets it from @node(rerun_on_resume=True) and must then ask with an interrupt_id that is the same on the run that asks and the run that resumes, since a new UUID on every run would ask again on every resume. In a loop, adk-python's request_input_rerun sample builds it from ctx.invocation_id and ctx.run_id, so each round asks anew (ADK 2.13). A node that had finished is skipped either way.
The deployment path on Agent Platform, with the alternative targets beside it. Old names survive in identifiers: the resource is a ReasoningEngine, the CLI target is agent_engine, the environment variable says AGENT_ENGINE.
OverviewStep through the mechanism with the buttons or the arrow keys.
The project: app/agent.py defines root_agent and the App; fast_api_app.py builds the FastAPI app with one Runner; a Dockerfile and agents-cli-manifest.yaml describe how to ship it.
agents-cli deploy (or adk deploy agent_engine, the SDK, Terraform) packages the project honouring .gcloudignore, then records the result in deployment_metadata.json. Since ADK 2.12, adk deploy agent_engine pins google-cloud-aiplatform[adk,agent_engines]>=2.2,<3 in the requirements it writes, and --extra_packages adds local packages for cloud_run and gke too, on the container's PYTHONPATH.
Agent Runtime builds the container image from the Dockerfile; on Cloud Run and GKE you build and push the same image yourself.
The container listens on 8080, which is all the runtime contract asks; the optional adapter routes /api/reasoning_engine and /api/stream_reasoning_engine serve :query and :streamQuery, next to ADK's own routes (/run_sse, sessions, /a2a/{app}, optional triggers).
The platform injects GOOGLE_CLOUD_AGENT_ENGINE_ID, so the scaffold switches to VertexAiSessionService (Agent Platform Sessions); Memory Bank attaches through context_spec; agents-cli deploy switches tracing on (GOOGLE_CLOUD_AGENT_ENGINE_ENABLE_TELEMETRY); the agent is registered in Agent Registry and runs as a service account or with Agent Identity, which agents-cli 1.10 and later give a new project by default.
Clients call :streamQuery on the reasoning engine resource, or any container route through the /api passthrough (…/reasoningEngines/v1/{resource}/api/…), including the A2A agent card and trigger endpoints.
agents-cli publish gemini registers the agent natively (ADK registration) in a Gemini Enterprise app, where end users meet it.
For governance, bind Agent Gateway at deploy time (requires Agent Identity): client-to-agent ingress and agent-to-anywhere egress with IAM, Model Armor and semantic policies; secrets arrive as environment variables from Secret Manager.
Alternative targets: the same image on Cloud Run or GKE, where you own scaling and choose sessions (in memory, Cloud SQL or agentengine://); these publish to Gemini Enterprise through their A2A agent card.
What an LlmAgent does between taking the turn and yielding its answer, as the 2.14 source has it. One pass down the middle is one model call; the arrow on the right is the loop. The hooks on the left run for every plugin first, then for the agent's own callbacks.
OverviewStep through the mechanism with the buttons or the arrow keys.
LlmAgent hands its turn to a flow: SingleFlow, or AutoFlow when a transfer is possible. The flow repeats one step until an event is final, and one step is one model call.
Twelve request processors fill a new LlmRequest, in a fixed order. basic sets the model and its config, instructions and identity write the system instruction, contents selects the history, and output_schema and agent_transfer add their tools. auth and request_confirmation add nothing to the request: they run a tool call again once its credential or its confirmation has arrived.
Three more processors resolve the tools. agent_tools asks each tool to add its declaration to the request and itself to tools_dict. If a toolset still lacks a credential, toolset_auth ends the invocation here.
Before the model: every plugin's before_model_callback in registration order, then the agent's own. A response returned here is used in place of the model's. The model is then not called, the call is not counted against max_llm_calls, and the after-model hooks are skipped.
The model is called with the request. If it raises, on_model_error_callback runs, plugins first; a response returned there stands in for the error and goes on like any response.
Every response, a streamed chunk included, passes after_model_callback, plugins first. A complete response that ended with STOP and holds nothing to act on, no parts or, since 2.11, only thought or whitespace text, is then marked as an error, MODEL_RETURNED_NO_CONTENT, instead of passing as an empty answer (under SSE streaming, where a closing chunk without parts is normal, only one with such parts). Then two response processors run: planning, and code execution, which can run the code the model wrote and ask for another step.
The response is copied onto the model's event, function calls get their ids, and the event goes to the Runner. If it is final, with no function call in it, the loop ends.
Function calls run as concurrent asyncio tasks. Around each one: the plugins' before_tool_callback, the agent's, the confirmation gate, the tool, then the after hooks. From a before hook any value that is not None replaces the tool.
All responses become one event, which is yielded. Unless that event is final (skip_summarization, or a long-running call still open) or hands the turn to another agent, the loop starts the next step with the responses in the history.
A voice agent does not take turns through run_async. The client opens one long call, run_live, and feeds it through a queue while events stream back. Dashed arrows travel towards the client. The path is experimental in ADK 2.14.
OverviewStep through the mechanism with the buttons or the arrow keys.
The client creates a LiveRequestQueue and calls run_live(live_request_queue=…, run_config=…); its arguments are keyword-only. One call is one invocation, however many turns follow. With no response_modalities in the RunConfig the reply is audio.
The Runner picks the agent to run and calls its run_live, which hands over to the flow. The request is built once for the whole session, so an instruction with state placeholders is rendered once.
The model's connect() opens the Live connection. Without a resumption handle the session's history is sent first, as text: earlier transcriptions become user and model turns, and audio parts are left out.
From here two tasks run side by side. The sending task takes requests off the queue and forwards them: audio and image blobs with send_realtime, text with send_content, activity signals when automatic voice activity detection is off.
The receiving task turns what the model sends into events: audio parts, transcription chunks marked partial, then the finished transcription. All of them are yielded; only non-partial events without inline media are appended to the session.
When the user speaks over the model, the Live API reports it and an event with interrupted=True reaches the client, which should stop playing audio. ADK itself only resets its transcription buffer.
A function call arrives. Blocking tools run and their responses are merged into one event, as in a text turn. An async-generator tool is started in the background and answers at once that its results are pending.
The function response returns to the model the way the user's input does: it is put on the queue with send_content, and the sending task forwards it as a tool response.
turn_complete arrives as an event of its own after the last segment. The session now holds the finished transcriptions, the tool call with its response and the turn_complete event. The audio is gone, unless save_live_blob stored it through the artifact service.
A connection lives about ten minutes. Before the server closes it, it sends go_away, and ADK connects again, with the resumption handle if it has one, at most five times in a row. A transfer to another agent ends the connection too: the target opens its own. The session ends when the client calls close() on the queue.
An agent on Agent Runtime that is bound to a gateway sends every outbound request through it. One tool call therefore meets the gateway twice: first as a function call in the model's response, where Semantic Governance (preview) can remove it, then as the request to the tool, where the access policy, the registry and Model Armor decide. Dashed arrows are returns.
OverviewStep through the mechanism with the buttons or the arrow keys.
A bound agent sends every outbound request through the gateway, its calls to the model included. The request travels over mTLS and carries the agent's own identity, not a service account's.
The model endpoint is a destination like any other: an access policy has to allow it. The model answers with a function call, which is a proposal to run a tool.
If Semantic Governance is connected, the gateway holds that response and sends the proposed call, the constraints written for this agent and the chat history to the policy engine. The engine sees model traffic only: its authorization policy matches the request path of each model API the agent calls, such as :generateContent for Gemini. A streamed response is not checked.
The engine answers ALLOW or DENY. Allowed, the response reaches the agent as the model wrote it. Denied, the function call is taken out, and a rationale or the policy's fixed denial message comes back in its place.
The agent now calls the tool: an MCP tools/call to a server outside. The gateway intercepts it. For MCP, and only for MCP, it reads the method, the tool name and the tool's registered annotations.
IAP checks the access policies: is there a rule that grants this agent identity iap.resources.egressViaIAP for this destination, and no deny rule that matches? If not, the agent receives a 403, Egress request is not authorized.
The destination's hostname is matched, exactly, to an entry in Agent Registry. The overview lists this after the access check; a host that is in no registry may be dropped before IAP sees it, and then leaves no entry in IAP's log.
If a Model Armor template is attached, the payload of the tools/call is screened. A block closes the connection.
The request is forwarded. The result returns the same way and is screened in turn. The gateway's request log keeps the decision with the MCP method and the tool name.
ADK runs an Antigravity SDK agent through AntigravityAgent: the SDK's harness, a local program, runs the loop, and ADK turns its steps into events. One turn opens a fresh SDK agent and so a fresh harness process, resumes the conversation by the id ADK kept in session state, and closes it again. Dashed arrows are returns.
OverviewStep through the mechanism with the buttons or the arrow keys.
The Runner calls run_async: plugin and agent before_agent hooks run first. The class then reads the id of its conversation from session state, under _antigravity_conversation_id_ and its own name; nothing else of the session is read.
The turn's SDK config is a deep copy of config. If the agent has ADK sub-agents, one tool per child is added. Two capture hooks come with any client tool the harness can call: an ADK child, a Python callable among the config's tools or, since ADK 2.12, an SDK subagent, which adds a third that records each invoke_subagent call. If an id was stored, it goes in as conversation_id with CREATE_OR_RESUME. A fresh SDK Agent is built on it and entered.
Entering starts the harness binary as a child process. A handshake on stdin and stdout returns a port and a session key; the SDK then sends the agent config as the first message over a local WebSocket, and the reply brings back a stored conversation's history; from then on both sides exchange JSON events over that socket. A stored conversation is reloaded from save_dir and its history comes back; an empty history after a resume clears the key and raises.
conversation.send carries the first text part of the user's message and nothing else: later text parts, images and files do not reach the harness.
The harness runs its own loop: it calls the model, runs the built-in tools itself after its policies have decided, compacts when its threshold is reached. ADK's model and tool hooks have no place in this loop, and max_llm_calls counts nothing.
Each step reaches the SDK over the socket and the class converts it: a complete response becomes one text event; a tool call a function call authored by the agent, its result a function response authored by the tool's name. Partial text exists only under StreamingMode.SSE; since ADK 2.12 the model's thinking is kept either way, as a thought part before the text or the function call it led to, and a step of an SDK subagent is authored by that subagent, with its trajectory_id, step_index and depth in custom_metadata; compaction and system steps become nothing, and a finish step a finish function call carrying the structured answer.
After the first event the class compares the SDK's conversation id with the stored one and, if it is new, yields an event of its own: no content, a state_delta with the key. The Runner appends it, so the next turn can resume. An unchanged id writes nothing.
An ADK sub-agent is one of the harness's client tools. The harness sends tool_call, the SDK runs the bridge callable, which runs the child in a new Runner with an empty in-memory session and returns its final text; the post_tool_call hook captures that result, and the class pairs it with the call as a function response.
The stream ends: results still owed a response are drained from the capture buffer, and since ADK 2.12 one more event with no content carries the turn's token count as usage_metadata. The SDK agent exits and the harness process stops. after_agent hooks run. A harness error leaves run_async as an exception, once the id is saved, with no error event.
Keyboard
With focus inside a flow: → and ← step, Home and End jump to the overview and the last step. A step's address is #/flows/event-loop&step=3.
Glossary
Every term with its one-line job, depth and Python symbol. The depth control in the header hides terms and comparisons deeper than the chosen level. The search box below narrows the table by name, alias, symbol or definition.
Terms
Definition
Symbol
Docs
Old names, new names
Google renamed the platform and several services on 22 April 2026. Code, URLs and many environment variables keep the old identifiers, and this table maps them.
Renamed products and the identifiers that still carry the old name
Was
Is now
Since
Still in code
Comparisons
Side by side, the choices the map cannot show at a glance.
Keyboard
Tab reaches the search box, the category filter, the column sort buttons and every link. The address of a term is #/glossary/term-id. The row is highlighted and scrolled into view.
How an ADK agent is built, run and operated on Google Cloud
A visual guide to the Agent Development Kit (Python) and to the managed services that an agent meets after it leaves your laptop. The guide also shows the Antigravity SDK beside ADK, and how ADK runs such an agent. The harness of the SDK (the program inside the package that runs the loop of the agent) brings much of what an ADK agent leaves to you. Read the guide at four depths. The control in the header sets how much the map, the flows, the comparison, the glossary and the disciplines show. On a reading path, the control opens the path of that depth.
New to ADK: start with the L50 path, ten stops in about fifteen minutes. Building agents already: the L100 path, then the L200 path. Facing a choice: the decision guides answer it in a few questions.
To find one thing, use the Search button in the header, or / on any page. The search finds a concept by any of its names, old product names included. It also finds a flow, a comparison, a decision guide or an error message pasted whole.
Documents
ADK Python 2.14.0 · agents-cli 1.13.0 · Antigravity SDK 0.1.23 · Gemini Enterprise Agent Platform docs as read on to
L50
At a glance: fourteen boxes that say what an ADK agent is and where it runs, in plain words. This is the guide's own level, below the L100 where Google Cloud's learning levels start. See the L50 path.
L100
Introductory: what each piece is and why it exists. The names, the shapes and the one-sentence jobs. See the L100 path.
L200
Technical: how the pieces fit, configure and deploy. Classes, parameters, the order things happen in and the managed services behind them. See the L200 path.
L300
Advanced technical: what happens inside, and what it takes to operate. One model call as the source has it, the graph engine, Live sessions, private networking, governance at the gateway and automated evaluation. See the L300 path.
Naming
Google renamed the platform on 22 April 2026: Vertex AI became Gemini Enterprise Agent Platform, and Agent Engine became Agent Runtime. The guide uses the current names and shows the old identifier wherever code still carries it.
Eight views
MapThe layered picture: your code, the ADK runtime underneath it, the serving layer, the managed services on Agent Platform, and the alternative targets. Click a box for its definition, its docs and, from L100, its Python symbol.
FlowsMechanisms stepped through one event at a time. At L100: the event loop and one invocation end to end. At L200: hook order, state scopes, how a graph Workflow runs and pauses for a person, and the path from code to a published agent. At L300: one model call, one Live session, one tool call through Agent Gateway and one turn of an AntigravityAgent. Switch on "Predict the next box" to pick, before each step, the box you expect to act.
PatternsSimple pictures of how agents work together: the four ways one agent calls another, seven common patterns, and agents inside a graph. One sentence each at L50, what you write from L100.
CompareA pure ADK agent beside an Antigravity SDK agent, part by part: what comes built in, what you switch on and what you write. One table that grows with the depth.
DecideWhich one should I use? Five common choices (the session service, the deploy target, how one agent involves another, a callback or a plugin, pure ADK or the Antigravity SDK). Each is a few questions that end in an answer with the comparison and the box on the map.
GlossaryEvery term with its one-line job, level and symbol. The crosswalk from old product names to new ones, and comparison tables.
DisciplinesPrompt, context, harness, loop and graph engineering, and the practices beside them. What each name means, who said so and when, and which parts of ADK and the Antigravity SDK it works on, at every depth.
PathsReading orders through the views for someone who learns top-down, one for each depth. Each path is also a tour for a talk: its stops one at a time, the words large at the foot of the screen. Each path ends in questions that check what its stops taught, each answered with why.
Facts are pinned to the versions above. Where Google marks something preview, the guide says so.
L100 path
The introductory path: what each piece is and why it exists, in the order a newcomer should meet them. Every stop opens a view with the depth set to L100. While the depth stays there, the Paths link in the header returns you here.
Start the tourThe seventeen stops below one at a time, for a talk. Each stop opens its view, with its words large at the foot of the screen. Each question under Check yourself comes after the stop it rests on, for a show of hands. Right arrow or Page Down goes to the next step, and Left arrow or Page Up goes to the step before. The A key shows the answer to a question, and Escape leaves the tour. The bar can switch the questions off, and it has a full screen button where the browser allows one.
Start with LlmAgent, the thing you write: a model, an instruction, a description, and the tools and sub-agents that it may use. The model decides the next step. Everything else on the map exists to run, structure or persist that decision.
A tool is a function with a schema the model can decide to call. Follow the four kinds: your own FunctionTool, Google's built-in tools, whole toolsets from an MCP server, and another agent called like a tool (a sub-agent in single_turn mode, or the older AgentTool).
Every message, tool call, tool result and final answer is an Event. The actions it carries, a state change or a transfer, are what the runtime applies.
The Runner takes an agent (or an App), a session service and optional artifact and memory services, and runs one user message at a time. Note the three services that the Runner uses. Everything persists in these services.
Step through the event loop. The agent yields an event, and the Runner commits the event through the services. The Runner forwards the event to the client and lets the agent resume. Nothing runs to completion in one go.
Step through one invocation: run_async, the session is loaded, the model asks for a tool, the tool runs, the model answers. Count the yields: each yield is a pause.
A Session is one conversation thread with its events and its State. The SessionService decides where the session lives. While you develop with adk web, the session is in a SQLite file in the agent's .adk folder. In tests, the session is in process memory. Other options are a database, or Agent Platform Sessions when deployed. The agent code is the same in each case.
The state of a session ends with the conversation, but user: and app: keys keep a few exact values longer. Memory is what the agent should be able to search for next week. Artifacts are the files that a conversation produces. Both have a development version (memory in the running program or a SQLite file, artifacts in the .adk folder) and a managed version in production.
If the order of steps must not depend on the judgement of the model, draw the order. A graph Workflow has nodes, edges and routes, and its nodes can be agents. Inside an LlmAgent, a second agent joins as a sub-agent: the model transfers to it, or calls it like a tool in single_turn mode.
Look at the four ways one agent calls another, at seven common patterns, and at agents inside a graph. Each picture has one sentence, and from L100 it also says what you write.
The same agent can hold a call. The run_live method keeps a two-way connection open. The user speaks and can interrupt, and the agent answers aloud and sees camera frames. Voice agents for support lines, shops and games work this way. Try it with the microphone in adk web. LiveKit connects the agent to phone calls, and Live is experimental in ADK 2.14.
adk create, adk web, adk run, adk eval, adk deploy. The dev UI is the local window into sessions, state, events and traces. Evaluation replays recorded conversations and scores them.
Agent Runtime hosts your agent as a container, scales it and switches the session service to the managed one. Cloud Run and GKE take the same container with more control and more to manage. Gemini Enterprise is where end users meet the result.
Three choices come first: where the agent runs, where its conversations live, and how one agent involves another. Each decision guide asks a few questions and ends in an answer. The answer links to the comparison table and the box on the map. Start with the deploy target. Its answer continues to the session service.
On this path, you assembled the agent, its tools, the session store and the deploy, but the Antigravity SDK ships an agent already assembled. A harness inside the package runs the loop with file, web, image and subagent tools on. The harness refuses shell commands, and keeps and compacts the conversation in a folder by itself. Read the Compare view at this depth with two questions. What does the harness do that ADK leaves to you, and what does ADK have that the harness lacks, such as a place to deploy? ADK runs such an agent as one of its own, and the L200 path shows how.
Read the five names of the ladder with their definitions and dates. For each name, see who named it, what it covers and leaves out, and what Google says with it. Google's ADK team adopted context engineering in its own words. The adk.dev site itself uses none of the five names. So this page is where the vocabulary of the trade meets the vocabulary of the docs.
Google renamed the platform in April 2026. Finish with the crosswalk so the old identifiers in code, agent_engine, VertexAiSessionService, reasoningEngines, stop being a surprise.
Seventeen stops, about an hour. When they feel familiar, switch the header to L200 and take the L200 path. That path goes under the same boxes: callbacks and plugins, hook order, state scopes, and the road from a container to a published agent.
Check yourself
Questions on what the stops above show: why something happens, what comes next, which part fits. Choose an answer: the page says at once whether it holds and why, and links the place the answer is read from.The answers follow the questions, each with why it holds and where it is read from.
Loading the questions.
L200 path
The technical path: how the pieces fit, configure and deploy. It goes under the same boxes the L100 path visited; every stop opens a view with the depth set to L200.
Start the tourThe twenty-five stops below one at a time, for a talk. Each stop opens its view, with its words large at the foot of the screen. Each question under Check yourself comes after the stop it rests on, for a show of hands. Right arrow or Page Down goes to the next step, and Left arrow or Page Up goes to the step before. The A key shows the answer to a question, and Escape leaves the tour. The bar can switch the questions off, and it has a full screen button where the browser allows one.
Read the L200 description: model, instruction with {state} templating, tools, sub_agents, output_schema and how it works alongside tools, output_key, include_contents, planner, code_executor, the eight callbacks, and 2.0's mode. Then follow the Connected list, where Agent Config is the same agent declared in YAML instead of Python.
Step through the hook order: plugins first, then the agent's callbacks, at every stage they share. Note which hooks exist only on plugins (on_user_message, before_run and after_run, on_event, on_agent_error, on_run_error), and that the model and tool error hooks exist on both.
Step through state scopes: a write becomes a delta on an event, the Runner commits it, and the prefix decides whether it is temporary, session-wide, per user or app-wide. Memory and artifacts are the stores that outlive the session.
InvocationContext for the agent, Context (formerly CallbackContext and ToolContext) for callbacks and tools: state, actions, artifacts, memory, confirmation, credentials.
The refinement loop, then the fan-out. Each node's output is the next node's node_input, and each event is in the session before the node goes on; the gate's route sends the draft back until the reviewer passes it, and a JoinNode waits for both branches of a fan-out, then hands on their outputs in one dict.
Customers name a design by its pattern: coordinator, pipeline, fan-out and gather, generate and review, refinement loop, human in the loop. The table says what builds each in ADK 2.14, a graph Workflow or the modes of sub-agents, and links the box and the flow step that show it.
ResumabilityConfig lets an agent's turn pause on a confirmation, request_input or a long-running tool and continue later by invocation id; a graph Workflow at the root pauses and resumes without it. Rewind restores a session to before an invocation.
adk-python's request_input sample, paused and answered. A node's RequestInput ends the call with the request in the session; the answer, a FunctionResponse with the request's id, resumes the same invocation, where the nodes that finished are skipped and the waiting node takes the answer as its output, unless rerun_on_resume runs it again.
One FastAPI app, one Runner: /run_sse, session routes, /a2a/{app}, optional trigger endpoints, the dev UI when enabled. RunConfig sets streaming per request.
Step through the deployment path: deploy packages, Agent Runtime builds and runs the container with the runtime contract, managed sessions, identity and registry; clients call :streamQuery or the /api passthrough; publish registers in Gemini Enterprise.
Build, Scale, Govern, Optimize. Click through Agent Gateway, Agent Identity and Agent Registry on the Govern row, then Cloud Trace, Agent Observability and Agent Platform Evals on the Optimize row.
Evalsets, criteria, the dev UI recording cases, adk eval and AgentEvaluator, user and environment simulation, prompt optimisation with adk optimize, and the managed service that agents-cli eval grades on.
Ten questions a review asks, from who can call the agent and whom it acts as to whether one user can read another's sessions, where the data lives and what Google keeps. Each row answers for the platform and for ADK 2.14 and agents-cli 1.13, with the status the pages give, and links the boxes that own its facts. Start at the first row: IAM Conditions bind principals, and the users one agent serves are kept apart by the user id it is given.
The error messages readers of ADK's issue tracker meet most, each traced to the piece it comes from: the session's app name, an MCP session's task, a tool's declaration, the history a request is built from, a state key in an instruction, what a deploy installs, the model's quota. Each row says the versions it applies to and what to change; a message pasted into Search lands on its row.
Twenty stops, about a hundred and ten minutes with the docs open beside them.
Antigravity and the disciplines
Five more stops, about an hour: the SDK agent that runs its own loop, read against the ADK parts the twenty stops above have set out, the disciplines that name the levers, and two choices to decide.
AntigravityAgent, from ADK's labs, wraps an Antigravity SDK config. The SDK's harness runs the loop and owns the conversation; ADK sends it the user's text and turns the steps that come back into events. The class takes no instruction, model or tools; those sit in the config. As the Runner's root it keeps one conversation per session through save_dir; with mode single_turn it is a sub-agent that its parent calls as a tool. The lens is on: the marks on the boxes say which parts the harness brings and which stay yours.
At this depth the comparison has its third column, the SDK agent inside ADK. Read it for the seams: ADK's model and tool hooks never fire, max_llm_calls is not enforced, the two state stores stay apart, only the first text part of the user's message is sent, partial events arrive only under SSE. What the harness refuses or sandboxes is decided by the SDK's policies, not by ADK's confirmation.
Antigravity reaches ADK by two roads: AntigravityAgent starts the SDK's harness on your machine, ManagedAgent calls an agent hosted by Google through the Managed Agents API. The table sets the two classes side by side: where the loop runs, what a turn sends, what ADK keeps to continue, tools, credentials, what a failure looks like, status.
At this depth every entry on the Disciplines page lists the parts of ADK and the SDK it works on, each linked and with the lever named: the fields of LlmAgent for prompt engineering, the context stack for context engineering, the Runner, App, hooks and evals for harness engineering, triggers, bounds and resumability for loop engineering, the graph for graph engineering. Read harness engineering first; it is the one whose shape the comparison already drew.
At this depth the decision guides add two to the three of L100: pure ADK, the Antigravity SDK or the SDK agent inside ADK, and a callback or a plugin. Walk the first with the comparison fresh in mind: each answer says why in one sentence read from the compare rows and the package, and links to the rows it rests on.
The L300 path goes under these concepts, into the internals and into operations.
Check yourself
Questions on what the stops above show: why something happens, what comes next, which part fits. Choose an answer: the page says at once whether it holds and why, and links the place the answer is read from.The answers follow the questions, each with why it holds and where it is read from.
Loading the questions.
L300 path
The advanced path: what happens inside, and what it takes to run an agent in production. It is for the person who writes plugins and custom nodes, debugs one turn, or operates agents behind a gateway. Map stops open at depth L300, where a box shows its L200 entry and then, marked L300, what the internals add.
Start the tourThe eighteen stops below one at a time, for a talk. Each stop opens its view, with its words large at the foot of the screen. Each question under Check yourself comes after the stop it rests on, for a show of hands. Right arrow or Page Down goes to the next step, and Left arrow or Page Up goes to the step before. The A key shows the answer to a question, and Escape leaves the tour. The bar can switch the questions off, and it has a full screen button where the browser allows one.
Step through an LlmAgent turn as the 2.14 source has it: the flow, the twelve request processors, the hooks before and after the model, the tool calls, and the loop back. One pass is one model call.
Read LLM flow, then LlmRequest and LlmResponse beside it: which processors run in which order, what contents holds and what it leaves out, when the loop ends, and where max_llm_calls is counted.
Fourteen hooks, plugins asked in registration order, the first answer ends the round. Then open Callbacks at this depth for what counts as an answer at each hook and what an answering hook skips.
A root LlmAgent or Workflow runs in a task of its own and hands its events over through a queue; a node waits until its event has been appended. Follow the Connected list to Event loop, Invocation and SessionService for what that guarantees.
How the calls of one response run together and come back as one event. Then Tool confirmation and Tool authentication: both end the turn with a synthetic function call that the client answers.
Workflow is its own scheduler: one task per triggered node, what a node with several predecessors receives, what fails a run. Workflow nodes, Routes, JoinNode and Parallel workers each add their rules.
ctx.run_node runs a child and, on resume, takes its result from the session, so loops are plain Python. RetryConfig gives the defaults, the delays and what a timeout raises; Resumability says why a graph resumes by replaying the session, not from a snapshot.
Step through a turn of the agent that runs on the Antigravity harness: the conversation id read from session state, a deep copy of the SDK config with one tool per ADK sub-agent, a fresh SDK Agent started for the turn, the first text part sent, each step converted to events, the id yielded as an event of its own, and what a harness error leaves behind. Count which of ADK's hooks the turn passes and which it never reaches.
The Antigravity SDK at this depth, as the 0.1.23 source has it: how the binary is found and started, the handshake over stdin and stdout and the WebSocket after it, why every strategy is local, where a built-in tool runs and where a Python callable does, which policy rules are decided in the binary and which call back, what save_dir holds and what resuming needs. Then AntigravityAgent for the generator path the Runner takes with it, the bridged sub-agent's own Runner, and the two statuses the two packages give it.
Step through a voice session: run_live with a LiveRequestQueue, one connection, two tasks side by side, an interruption, a tool call, and what the session keeps when the turn completes.
What does not apply in a Live session and where its limits come from. Then RunConfig for the Live settings, Streaming for how the event flags read there, and API server for the /run_live WebSocket.
Which updates create a revision, what is fixed at creation, the instance limits. Then Private networking: the PSC interface and DNS peering, VPC Service Controls and CMEK.
The Managed Agents API and the part of it that ADK's ManagedAgent uses. Then Skill Registry, and why ADK reads the skills of Agent Registry instead; Agent Skills has the skill lifetimes that 2.10 added.
Step through an outbound tool call of a bound agent. It meets the gateway twice: as the model's proposal, which Semantic Governance can remove, and as the request, which IAP checks, Agent Registry matches and Model Armor screens.
Agent Gateway, Agent Identity and Agent Registry at this depth, then IAM access policies, Semantic Governance and Model Armor: who may reach what, what a policy can see, and what each refusal looks like.
What adk eval does with a case and when a case passes. Evalsets and Eval criteria have the files and the seventeen metrics; Agent Platform Evals says which agents-cli command runs on your machine and which on the service.
Scenario cases that a model plays, tool results faked by environment simulation, and adk optimize searching for a better root instruction. The optimiser is experimental, and all of it runs on your machine.
At L300 each entry gives the definitions as their sources wrote them, the unit of work each name claims, how the sources relate the rungs and where they disagree: whether harness engineering sits inside context engineering or delivers it, who coined what, and whether loop and graph engineering are disciplines or renamed cron jobs and a meme. Every quote carries its date; open the sources under each entry.
Eighteen stops, about five hours with the source and the docs open beside them, best taken in several sittings. An L300 entry names the class, field or command it describes, so that it can be checked against ADK 2.14.0 and the platform docs; what the package deprecates is left out. The L200 path covers the same boxes one level up.
Check yourself
Questions on what the stops above show: why something happens, what comes next, which part fits. Choose an answer: the page says at once whether it holds and why, and links the place the answer is read from.The answers follow the questions, each with why it holds and where it is read from.
Loading the questions.
L50 path
At a glance: the fourteen boxes that a first conversation about ADK needs, in reading order. Eight stops are on the map, then come the Compare view and the Disciplines page. Every stop opens with the depth set to L50. While the depth stays there, the Paths link in the header returns you here.
Start the tourThe ten stops below one at a time, for a talk. Each stop opens its view, with its words large at the foot of the screen. Each question under Check yourself comes after the stop it rests on, for a show of hands. Right arrow or Page Down goes to the next step, and Left arrow or Page Up goes to the step before. The A key shows the answer to a question, and Escape leaves the tour. The bar can switch the questions off, and it has a full screen button where the browser allows one.
The box you write. The agent names a Gemini model, says in an instruction what the agent is for, and lists what the agent may use. On each turn, the model reads the conversation and decides: answer, call a tool, or transfer the conversation.
A tool is anything the agent can call. A tool can be one of your functions, a Google tool such as search, or another agent. A tool can also be a set of tools that another program offers over MCP, the common way that tool servers describe their tools. The model sees only names and descriptions, and chooses by them.
An agent can transfer the conversation to a specialist that it lists as a sub-agent. Most real systems take this shape: a coordinator that routes to a billing agent and a technical agent.
You never call the model yourself. The Runner loads the conversation, calls the agent, saves every step and streams the results to you. Any host of the agent, your laptop or Google's runtime, drives the agent through a Runner.
A Session is one conversation with a little state attached. The session ends when the conversation ends. Memory is what should still be known next week, per user. During development, a file in your project keeps the conversations, and the running program keeps memory (or a file, if you ask). In production, managed services keep both.
The adk command line creates a project and opens a browser window. In that window, you chat with the agent and inspect every step. The command line also runs evaluations and deploys the agent. The code is the same before and after.
Evaluation replays recorded conversations and scores the answers and the tool calls. The loop is: change the instruction, run the evaluation, read the score. The loop runs before each deploy.
Agent Runtime is Google's managed host. Agent Runtime packages your code, runs the agent at a web address and scales the agent. Agent Runtime also connects managed Sessions and Memory Bank. When you publish the agent, employees find it in Gemini Enterprise. All of these services are the Gemini Enterprise Agent Platform, the band at the bottom of the map.
Google also ships an agent that comes assembled. The Antigravity SDK runs the loop of the agent in a harness, a program inside the package. File tools, helper agents and a rule set are already on. The Compare view puts this agent beside a pure ADK agent, part by part: what each build brings, what you switch on, what you write. ADK can run such an agent as one of its own, and the deeper paths show how.
Prompt engineering, context engineering, harness engineering, loop engineering, graph engineering: five names. Each name covers a bigger piece of the work than the one before, from writing one instruction to wiring many runs together. The Disciplines page says what each name means in plain words, and who said so and when. The page also links each discipline to the boxes that it works on.
Ten stops, about fifteen minutes. The L100 path then adds the names behind each box: events, state, the session service, graph workflows, the kinds of tools.
Check yourself
Questions on what the stops above show: why something happens, what comes next, which part fits. Choose an answer: the page says at once whether it holds and why, and links the place the answer is read from.The answers follow the questions, each with why it holds and where it is read from.
Loading the questions.
Map
The layered picture of an ADK agent and everything it runs on: what you write at the top, the managed services at the bottom. The header sets the depth. Click a box or use the index for its definition, symbol and docs.
Loading the map.
Keyboard
Tab reaches the map. Arrow keys move between boxes, Enter selects, Esc clears, [ and ] walk along the connections. To let go of a box with the mouse, click it again, click the empty ground, or use Clear selection in the panel. The address of a box is #/map/id. Add &l=200 for depth.
Patterns
Simple pictures of how agents work together. The first part shows the four ways one agent calls another. The second part shows seven common patterns, and the third part shows agents inside a graph. A rounded box is your agent or your function, and a plain box is a person or the start of a graph. A dashed arrow is a return.
At L50 each pattern has one sentence. From L100 it also says what you write. The glossary and the map have the detail.
Calling another agent
An agent can give work to another agent in four ways. The four ways differ in who talks to the user and in how control comes back.
Transfer
The parent gives the whole conversation to a specialist. The specialist talks to the user until it transfers back.
A user writes to a coordinator. The coordinator transfers to a specialist, which replies to the user itself until it transfers back.
List the specialist in the parent's sub_agents and set no mode. The model calls transfer_to_agent when the description of the specialist fits the request. The specialist sees the whole conversation and the session state. Control comes back only with another transfer.
The parent asks a specialist to do one task. The specialist can ask the user questions, then it returns a result.
A parent gives a specialist in task mode a typed task. The specialist may ask the user questions, then returns its result with finish_task to the parent, which keeps the conversation.
Set mode='task' on the sub-agent. The model of the parent calls the specialist as a tool with typed input. The specialist works with the user until it calls finish_task. The parent gets that result and keeps the conversation.
The parent asks a specialist for one answer. The specialist does not talk to the user. Several specialists can work at the same time.
A parent calls two specialists in single-turn mode at the same time. Each gets the call's arguments only and returns one reply to the parent. The user talks only to the parent.
Set mode='single_turn' on the sub-agent. The model of the parent calls the specialist as a tool. The specialist gets only the arguments of the call and returns its reply as the result. It shares the session state with the parent. ADK prefers this mode to AgentTool. Set disallow_transfer_to_parent=True and disallow_transfer_to_peers=True on each helper. Otherwise a model can try a transfer instead of an answer, and the parent then calls the helper again.
The parent uses another agent like a tool. The other agent works in a separate session and returns a result.
A parent calls AgentTool, which runs the specialist with its own Runner in a new session and returns its last reply as the function response. A copy of the state goes in and the specialist's changes come back.
Put AgentTool(agent=…) in the tools of the parent. The call runs the agent with its own Runner and a new session. The agent gets a copy of the state and returns its last reply. ADK copies its state changes back. One agent can serve many parents this way.
Seven common patterns, built from the four ways above or from a graph. With sub-agents, the model chooses the next step. In a graph Workflow, your edges choose the next step.
Coordinator
One agent reads each request and sends it to the right specialist.
A user writes to a coordinator, which transfers each request to one of three specialists: billing, technical or other.
The coordinator lists the specialists in sub_agents. Its model reads the description of each specialist and transfers the request to the best match. In a graph, a ClassifierNode makes the same choice and gives a route.
Agents run one after another. Each step uses the result of the step before.
A graph Workflow runs three agents in a fixed order, draft, review and format. Each passes its result to the next through state.
Write the steps as one chain of edges in a graph Workflow. Each agent saves its result in state with output_key. The next agent reads that result in its instruction.
Several agents work at the same time. One step then collects all their results.
A graph Workflow starts three readers in parallel. A JoinNode waits for all three, then a summary step uses their results.
In a graph Workflow, give one node edges to several nodes. These nodes run in parallel. A JoinNode waits for all of them, and the next node uses all the results.
A root agent divides a large job. Managers divide their parts again for their workers.
A root agent gives typed tasks to two managers in task mode, and each manager divides its task again among two workers.
Each level lists the level below in sub_agents. With mode='task', each manager gets a typed task and returns a typed result. The root agent keeps the conversation with the user.
One agent writes a draft. A second agent checks it.
A writer saves its draft in state with output_key, and a reviewer reads the draft from state in its instruction.
The writer saves its draft in state with output_key='draft'. The reviewer reads {draft} in its instruction and gives its review. In a graph, the two agents are one chain of edges.
A writer and a reviewer repeat until the draft is good enough.
A writer and a reviewer run in turn. A gate routes revise back to the writer, or done to accept the draft.
A routed edge goes back from a gate to the writer. The gate gives the route revise or done from the review. Count the rounds in state, and stop after a maximum.
The run stops and asks a person. The answer of the person continues the run.
A graph asks a person with RequestInput and pauses. The person's answer resumes the run, and a decide step routes revise back to the draft or goes on.
A graph node yields RequestInput, and the run pauses. The client sends the answer of the person, and the run resumes at that node. A tool can also ask for a confirmation with require_confirmation=True.
An agent in a graph can have helpers, can ask the user, or can run a graph of its own. The mode of each agent decides what it can do. Each picture here was run on ADK 2.14.
Helpers inside a step
One step of a graph calls helper agents and uses their answers. Then the graph goes on to the next step.
A graph step calls its two single-turn helpers as tools and gets their replies. Then the graph goes on to the next step.
Give the agent of the step sub_agents with mode='single_turn'. The step stays a single-turn node, and it calls each helper as a tool. The helpers answer only the step, and several helpers can run at the same time. Do not give the step a helper in task mode. A single-turn step never starts that helper, and a real model then calls it again and again. Set disallow_transfer_to_parent=True and disallow_transfer_to_peers=True on each helper. Otherwise a model can try a transfer instead of an answer, and the parent then calls the helper again.
One step of a graph talks with the user until it has what it needs. Then the graph goes on.
A graph step in task mode asks the user a question. The graph waits at that step. The next message of the user answers, and finish_task passes the result on.
Make the step an agent with mode='task'. The graph waits at that step between messages. When the agent calls finish_task, its result goes to the next step, and output_key also saves the result in state.
An agent runs a whole graph like one tool. The agent gets the result of the last step.
An agent calls a Workflow listed in its tools like one tool. The graph runs its two steps, and the last step's output comes back as the tool's result.
Put a Workflow in the tools of the agent. The model calls the graph by its name, and the graph runs its steps in order. The output of the last step comes back as the result of the tool.
A step can give the conversation to a specialist, but only for one turn. On the next message, the graph starts again at the beginning.
A graph step transfers to its specialist, which answers. Step B runs in the same turn, and the next message starts the graph again at START.
An agent node with sub_agents can call transfer_to_agent. The specialist answers, and the next step runs in the same turn. On the next message, the graph starts again at START. Use a step in task mode when the step must keep the conversation.