Open
Description
Summary
Request support for configuring individual RunConfig
settings for each sub-agent and coordinator agent in Google ADK, rather than the current shared configuration approach.
Background
Currently, Google ADK uses a shared RunConfig
approach where:
RunConfig
is passed toRunner.run_async()
and stored inInvocationContext
- All agents (coordinator and sub-agents) inherit the same configuration from the invocation context
- This limits fine-grained control over individual agent behavior
Use Case
We are investigating latency issues in a multi-agent system where:
- The coordinator agent should have a low LLM call limit (e.g.,
max_llm_calls=1
) for quick routing decisions - Specialist sub-agents need higher limits (e.g.,
max_llm_calls=5
) for complex processing - Different agents may require different streaming modes, timeout settings, or other configurations
Current Limitations
- Shared InvocationContext: The current architecture shares
InvocationContext
(includingrun_config
) across all agents in a single invocation - No Built-in Per-Agent Config: There's no native ADK feature for per-agent RunConfig
- LLM Call Counting: The
max_llm_calls
limit is enforced at the invocation level, not per agent - Workarounds are Complex: Current solutions require custom agent implementations or runner modifications
Proposed Solution
Option 1: Agent-Level RunConfig Property
class LlmAgent(BaseAgent):
agent_run_config: Optional[RunConfig] = None
async def _run_async_impl(self, ctx: InvocationContext):
# Use agent-specific config if available, otherwise fall back to context config
effective_config = self.agent_run_config or ctx.run_config
modified_ctx = ctx.model_copy(update={'run_config': effective_config})
# ... rest of implementation
Option 2: RunConfig Override in Agent Constructor
coordinator = LlmAgent(
name="Coordinator",
run_config=RunConfig(max_llm_calls=1, streaming_mode=StreamingMode.NONE),
# ... other params
)
specialist = LlmAgent(
name="Specialist",
run_config=RunConfig(max_llm_calls=5, streaming_mode=StreamingMode.SSE),
# ... other params
)
Option 3: Runner-Level Agent Configuration Map
runner = Runner(
agent=root_agent,
agent_configs={
"Coordinator": RunConfig(max_llm_calls=1),
"SpecialistAgent": RunConfig(max_llm_calls=5),
}
)
Benefits
- Fine-grained Control: Different agents can have optimized configurations for their specific roles
- Performance Optimization: Coordinator agents can be limited to quick decisions while specialists can perform complex reasoning
- Resource Management: Better control over LLM usage and costs per agent type
- Flexibility: Supports diverse multi-agent architectures with varying requirements
Implementation Considerations
- Backward compatibility with existing shared RunConfig approach
- Clear precedence rules (agent-specific > invocation-level > default)
- Documentation and examples for common use cases
- Performance impact of per-agent configuration management
Related Files
google/adk/agents/run_config.py
- RunConfig class definitiongoogle/adk/agents/invocation_context.py
- InvocationContext with shared run_configgoogle/adk/agents/base_agent.py
- Base agent implementationgoogle/adk/runners.py
- Runner implementation with run_config handling
Additional Context
This feature request emerged from a latency investigation where we needed to add comprehensive timing logs to identify performance bottlenecks in a multi-agent system. The ability to configure individual agents would significantly improve debugging and optimization capabilities.