All skills
google avatar

/adk-architecture

@f7a1cd4
by googlegoogle/adk-python22k stars
4,084

Explains how the ADK runtime fits together: the node and graph execution model, Context and Event flow, checkpoint and resume, tracing, and the rules governing the public API surface. Use when answering "how does X work" about ADK internals, tracing where an event or a piece of state comes from, deciding where a new capability belongs, reviewing a change to BaseNode, Workflow, Runner, Agent, Event or Context, working out why a node re-ran or stayed waiting after a resume, or judging whether a change breaks the public API. Don't use for assembling an agent from existing pieces (use adk-agent-builder), diagnosing one failing run or test (use adk-debug), or formatting and naming conventions (use adk-style).

Use this Skill: https://skilld.dev/gh/google/adk-python/adk-architecture

This session only. Nothing lands on disk.

referencesinterface-base-node.md

≈1.3k tokens on demand. Your agent reads this file only when SKILL.md points to it.

BaseNode

BaseNode is the primitive unit of execution in the workflow runtime. Every computation — LLM calls, tool execution, orchestration — is a node. It is a Pydantic BaseModel subclass.

The node contract

Every node follows a two-method pattern:

  • run() is @final — normalizes yields to Events. Never override.
  • _run_impl() is the extension point — subclasses implement their logic here as an async generator.
class MyNode(BaseNode):
    async def _run_impl(self, *, ctx, node_input):
        result = do_work(node_input)
        yield result  # becomes Event(output=result)

Why this split: run() guarantees consistent normalization regardless of what the subclass does. The subclass only thinks about its domain logic.

Normalization rules (run() applies these to each yield):

  • None → skipped
  • Event → pass through
  • RequestInput → interrupt Event
  • any other value → Event(output=value)

Generator conventions:

A node can yield three types of data:

  • Output — the node's result value. Flows between nodes (parent reads ctx.output after child completes). At most one per execution (second raises ValueError).
  • Message — user-visible content streamed to the end user (e.g., progress text, partial responses). Multiple allowed.
  • Route — Workflow-specific concept. Triggers conditional edges in the graph. Set via ctx.route or event.actions.route.

Additional rules:

  • Yielding nothing produces no output event
  • yield None is silently skipped

A custom node interacts with the runtime through two arguments:

  • ctx (Context) — communicate results to the parent node
  • node_input — data passed by the parent/orchestrator

Output and streaming

Three ways to produce output (pick one per execution):

# 1. Yield a value (most common)
async def _run_impl(self, *, ctx, node_input):
    yield compute(node_input)

# 2. Set ctx.output directly
async def _run_impl(self, *, ctx, node_input):
    ctx.output = compute(node_input)
    return
    yield  # generator contract

# 3. Yield an Event with output
async def _run_impl(self, *, ctx, node_input):
    yield Event(output=compute(node_input))

A second output raises ValueError — at most one per execution.

Streaming messages — yield Events with message to send user-visible text (message is an alias for content on Event):

async def _run_impl(self, *, ctx, node_input):
    yield Event(message='working...')
    yield final_result  # this is the output

State and routing

Mutating state:

async def _run_impl(self, *, ctx, node_input):
    ctx.state['key'] = 'value'  # recorded as state_delta
    yield result

Setting route for conditional edges:

async def _run_impl(self, *, ctx, node_input):
    ctx.route = 'approve' if score > 0.8 else 'reject'
    yield node_input

Advanced: child nodes and HITL

Running child nodes via ctx.run_node():

async def _run_impl(self, *, ctx, node_input):
    child_result = await ctx.run_node(some_node, node_input)
    yield f'child said: {child_result}'

Requires rerun_on_resume = True on the calling node.

Requesting interrupt (HITL):

async def _run_impl(self, *, ctx, node_input):
    if ctx.resume_inputs and 'fc-1' in ctx.resume_inputs:
        yield f'approved: {ctx.resume_inputs["fc-1"]}'
        return
    yield Event(long_running_tool_ids={'fc-1'})

Configuration reference

Field Type Default Purpose
name str required Unique identifier. Validated: must be a valid Python identifier.
description str '' Human-readable description
rerun_on_resume bool False Re-execute from scratch on resume (required for ctx.run_node()). When False the node completes immediately using the resume input as its output.
wait_for_output bool False Stay WAITING until output or route is yielded, so predecessors can re-trigger the node (join nodes). Never yielding either deadlocks the node.
retry_config RetryConfig | None None Retry on failure. Not persisted, so the count restarts after a resume.
timeout float | None None Max execution time in seconds; exceeding it raises NodeTimeoutError, which retry_config can retry.
input_schema SchemaType | None None Validate/coerce input data before run()
output_schema SchemaType | None None Validate/coerce output data
state_schema type[BaseModel] | None None Declare expected ctx.state keys and types; mutations are validated at runtime. Children inherit it unless they declare their own. Prefixed keys (app:, user:, temp:) bypass validation.

START (in the same module) is a sentinel BaseNode marking a graph's entry point. It is never executed — the Workflow seeds triggers for its successors directly.

Source: SKILL.md on GitHub

No alerts7d3 checks · Risk SAFE
  • Gen Agent Trust Hub7d

    This skill consists of comprehensive architectural documentation for the Agent Development Kit (ADK). It provides technical guidance on the framework's node execution model, context scoping, and observability patterns. No security considerations were identified as the content is purely informational and follows standard developer documentation practices.

  • Socket7d

    No alerts

  • Snyk7d

    Risk: LOW · No issues

Signed by skilld at f7a1cd4. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated last week

README badge

README badge for google/adk-python/adk-architecture