Skip to main content

Tutorial 20: Agent Configuration with YAML

Goal: Master declarative agent configuration using YAML files to define agents, tools, and behaviors without writing Python code, enabling rapid prototyping and configuration management.

Prerequisites:

  • Tutorial 01 (Hello World Agent)
  • Tutorial 02 (Function Tools)
  • Tutorial 06 (Multi-Agent Systems)
  • Basic understanding of YAML syntax

What You'll Learn:

  • Creating agent configurations with root_agent.yaml
  • Understanding AgentConfig and LlmAgentConfig schemas
  • Configuring tools, models, and instructions in YAML
  • Multi-agent systems in configuration files
  • When to use YAML vs Python code
  • Loading and validating configurations
  • Best practices for config management

Time to Complete: 45 minutes


Why YAML Configuration Matters

Problem: Writing Python code for every agent configuration requires development expertise and makes rapid iteration difficult.

Solution: YAML configuration enables declarative agent definitions that can be edited without code changes.

Benefits:

  • 🚀 Rapid Prototyping: Change configurations without coding
  • 📝 Readable: Human-friendly format
  • [FLOW] Version Control: Easy to track config changes
  • 🎯 Separation: Configuration separate from implementation
  • 👥 Accessibility: Non-developers can modify agents
  • 🔧 Reusable: Share configurations across projects

Use Cases:

  • Quick agent prototyping
  • Configuration-driven deployments
  • Multi-environment setups (dev, staging, prod)
  • Agent marketplace/templates
  • Non-technical team member modifications

Status: YAML configuration is marked as @experimental in ADK. API may change.


API Verification

Source Verified: Official ADK source code (version 1.16.0+)

Correct API: config_agent_utils.from_config(config_path)

Common Mistake: Using AgentConfig.from_yaml_file() - this method does not exist. Instead, use config_agent_utils.from_config() which loads the YAML file and returns a ready-to-use agent instance.

Verification Date: October 2025


1. YAML Configuration Basics

What is root_agent.yaml?

root_agent.yaml is the main configuration file that defines an agent and its sub-agents declaratively.

Location: Place in project root or specify path explicitly.

Basic Structure:

root_agent.yaml
├── name (required)
├── model (required)
├── description (optional)
├── instruction (optional)
├── generate_content_config (optional)
│ ├── temperature
│ ├── max_output_tokens
│ ├── top_p
│ └── top_k
├── tools (optional)
│ └── [tool_name, ...]
└── sub_agents (optional)
└── [agent_config, ...]
# root_agent.yaml

name: my_agent
model: gemini-2.0-flash
description: A helpful agent
instruction: |
You are a helpful assistant that answers questions
accurately and concisely.

generate_content_config:
temperature: 0.7
max_output_tokens: 1024

tools:
- type: function
name: get_weather
description: Get current weather for a location

sub_agents:
- name: specialized_agent
model: gemini-2.0-flash
description: Specialized agent for specific tasks

Creating Configuration Project

# Create new config-based project
adk create --type=config my_agent_config

# Directory structure created:
# my_agent_config/
# root_agent.yaml # Agent configuration
# tools/ # Custom tool implementations
# README.md

2. AgentConfig Schema

Core Fields

Source: google/adk/agents/agent_config.py

# Required fields
name: agent_name # Unique identifier
model: gemini-2.0-flash # Model to use

# Optional fields
description: "Agent purpose" # Brief description
instruction: | # System instruction
Multi-line instruction
for the agent

# Content generation config
generate_content_config:
temperature: 0.7 # 0.0-1.0 (creativity)
max_output_tokens: 2048 # Max response length
top_p: 0.95 # Nucleus sampling
top_k: 40 # Top-k sampling

# Tools configuration
tools:
- type: function
name: tool_name
# ... tool config

# Sub-agents
sub_agents:
- name: sub_agent_1
# ... agent config

Model Options

# Gemini 2.0 models (recommended)
model: gemini-2.0-flash # Fast, efficient
model: gemini-2.0-flash-thinking # With thinking capability

# Gemini 1.5 models
model: gemini-1.5-flash # Fast, cost-effective
model: gemini-1.5-pro # High quality

# Live API models
model: gemini-2.0-flash-live-preview-04-09 # Vertex AI Live
model: gemini-live-2.5-flash-preview # AI Studio Live

3. Real-World Example: Customer Support System

Let's build a complete customer support system using YAML configuration.

Complete Configuration

# root_agent.yaml

name: customer_support
model: gemini-2.0-flash
description: Customer support agent with various tools

instruction: |
You are a customer support agent. Your role is to:

1. Understand customer inquiries
2. Use available tools to provide accurate information
3. Provide comprehensive solutions

Available tools:
- check_customer_status: Check if customer is premium member
- log_interaction: Log customer interaction for records
- get_order_status: Get status of an order by ID
- track_shipment: Get shipment tracking information
- cancel_order: Cancel an order (requires authorization)
- search_knowledge_base: Search technical documentation
- run_diagnostic: Run diagnostic tests
- create_ticket: Create support ticket for escalation
- get_billing_history: Retrieve billing history
- process_refund: Process refund (requires approval for amounts > $100)
- update_payment_method: Update stored payment method

Guidelines:
- Always be polite and professional
- Provide specific information when available
- Escalate complex issues when necessary

generate_content_config:
temperature: 0.5
max_output_tokens: 2048

tools:
- name: customer_support.tools.check_customer_status
- name: customer_support.tools.log_interaction
- name: customer_support.tools.get_order_status
- name: customer_support.tools.track_shipment
- name: customer_support.tools.cancel_order
- name: customer_support.tools.search_knowledge_base
- name: customer_support.tools.run_diagnostic
- name: customer_support.tools.create_ticket
- name: customer_support.tools.get_billing_history
- name: customer_support.tools.process_refund
- name: customer_support.tools.update_payment_method

Tool Implementations

# tools/customer_tools.py

"""
Tool implementations for customer support system.
These functions are referenced by name in root_agent.yaml.
"""

def check_customer_status(customer_id: str) -> Dict[str, Any]:
"""
Check if customer is premium member.

Args:
customer_id: Customer identifier

Returns:
Dict with status, report, and customer tier information
"""
# Simulated lookup - in production, would query database
premium_customers = ['CUST-001', 'CUST-003', 'CUST-005']

is_premium = customer_id in premium_customers
tier = 'premium' if is_premium else 'standard'

return {
'status': 'success',
'report': f'Customer {customer_id} is {tier} member',
'data': {
'customer_id': customer_id,
'tier': tier,
'is_premium': is_premium
}
}


def log_interaction(customer_id: str, interaction_type: str, summary: str) -> Dict[str, Any]:
"""
Log customer interaction for records.

Args:
customer_id: Customer identifier
interaction_type: Type of interaction (inquiry, complaint, etc.)
summary: Brief summary of the interaction

Returns:
Dict with status and confirmation
"""
# In production, would log to database or CRM system
print(f"[LOG] {customer_id} - {interaction_type}: {summary}")

return {
'status': 'success',
'report': 'Interaction logged successfully',
'data': {
'customer_id': customer_id,
'interaction_type': interaction_type,
'summary': summary,
'timestamp': '2025-10-13T10:00:00Z' # Would be actual timestamp
}
}


def get_order_status(order_id: str) -> Dict[str, Any]:
"""
Get status of an order by ID.

Args:
order_id: Order identifier

Returns:
Dict with order status information
"""
# Simulated order lookup - in production, would query order database
orders = {
'ORD-001': {'status': 'shipped', 'date': '2025-10-08'},
'ORD-002': {'status': 'processing', 'date': '2025-10-10'},
'ORD-003': {'status': 'delivered', 'date': '2025-10-07'},
'ORD-004': {'status': 'cancelled', 'date': '2025-10-09'}
}

order = orders.get(order_id)
if not order:
return {
'status': 'error',
'error': f'Order {order_id} not found',
'report': f'No order found with ID {order_id}'
}

return {
'status': 'success',
'report': f'Order {order_id} status: {order["status"]}',
'data': {
'order_id': order_id,
'status': order['status'],
'order_date': order['date']
}
}


def track_shipment(order_id: str) -> Dict[str, Any]:
"""
Get shipment tracking information.

Args:
order_id: Order identifier

Returns:
Dict with tracking information
"""
# Simulated tracking lookup - in production, would query shipping API
tracking = {
'ORD-001': {
'carrier': 'UPS',
'tracking_number': '1Z999AA10123456784',
'estimated_delivery': '2025-10-10',
'status': 'In transit'
},
'ORD-003': {
'carrier': 'FedEx',
'tracking_number': '7898765432109',
'estimated_delivery': 'Delivered on 2025-10-07',
'status': 'Delivered'
}
}

info = tracking.get(order_id)
if not info:
return {
'status': 'error',
'error': f'No tracking available for order {order_id}',
'report': f'No tracking information found for {order_id}'
}

return {
'status': 'success',
'report': f'Tracking: {info["carrier"]} {info["tracking_number"]}, ETA: {info["estimated_delivery"]}',
'data': {
'order_id': order_id,
'carrier': info['carrier'],
'tracking_number': info['tracking_number'],
'estimated_delivery': info['estimated_delivery'],
'status': info['status']
}
}


def cancel_order(order_id: str, reason: str) -> Dict[str, Any]:
"""
Cancel an order (requires authorization).

Args:
order_id: Order identifier
reason: Reason for cancellation

Returns:
Dict with cancellation status
"""
# Simulated order cancellation - in production, would have authorization checks
cancellable_orders = ['ORD-001', 'ORD-002'] # Only processing/shipped orders can be cancelled

if order_id not in cancellable_orders:
return {
'status': 'error',
'error': f'Order {order_id} cannot be cancelled',
'report': f'Order {order_id} is not eligible for cancellation'
}

return {
'status': 'success',
'report': f'Order {order_id} cancelled. Reason: {reason}',
'data': {
'order_id': order_id,
'reason': reason,
'refund_status': 'pending',
'cancelled_at': '2025-10-13T10:00:00Z'
}
}


def search_knowledge_base(query: str) -> Dict[str, Any]:
"""
Search technical documentation.

Args:
query: Search query

Returns:
Dict with relevant documentation
"""
# Simulated knowledge base search - in production, would query documentation system
kb = {
'login': 'To reset password, go to Settings > Security > Reset Password',
'connection': 'Check internet connection and restart the app',
'error': 'Clear app cache: Settings > Apps > Clear Cache',
'update': 'Go to Settings > Updates > Check for Updates',
'sync': 'Ensure device is connected and try Settings > Sync > Sync Now'
}

query_lower = query.lower()
results = []

for key, value in kb.items():
if key in query_lower:
results.append({
'topic': key,
'solution': value
})

if not results:
return {
'status': 'success',
'report': 'No matching article found',
'data': {
'query': query,
'results': [],
'suggestion': 'Try searching for: login, connection, error, update, sync'
}
}

return {
'status': 'success',
'report': f'Found {len(results)} relevant article(s)',
'data': {
'query': query,
'results': results
}
}


def run_diagnostic(issue_type: str) -> Dict[str, Any]:
"""
Run diagnostic tests.

Args:
issue_type: Type of issue to diagnose

Returns:
Dict with diagnostic results
"""
# Simulated diagnostic - in production, would run actual diagnostic tests
diagnostics = {
'connection': {
'tests': ['Network connectivity', 'Server response', 'DNS resolution'],
'result': 'All systems operational',
'recommendation': 'Clear cache and restart'
},
'performance': {
'tests': ['Memory usage', 'CPU usage', 'Disk space'],
'result': 'Performance within normal range',
'recommendation': 'Close unused applications'
},
'login': {
'tests': ['Authentication service', 'Session management', 'Password validation'],
'result': 'Authentication systems operational',
'recommendation': 'Check password and try again'
}
}

diagnostic = diagnostics.get(issue_type.lower())
if not diagnostic:
return {
'status': 'error',
'error': f'Unknown issue type: {issue_type}',
'report': f'No diagnostic available for {issue_type}'
}

return {
'status': 'success',
'report': f'Diagnostic for {issue_type}: {diagnostic["result"]}. Suggested: {diagnostic["recommendation"]}',
'data': {
'issue_type': issue_type,
'tests_run': diagnostic['tests'],
'result': diagnostic['result'],
'recommendation': diagnostic['recommendation']
}
}


def create_ticket(customer_id: str, issue: str, priority: str) -> Dict[str, Any]:
"""
Create support ticket for escalation.

Args:
customer_id: Customer identifier
issue: Description of the issue
priority: Priority level (low, medium, high, urgent)

Returns:
Dict with ticket information
"""
# Simulated ticket creation - in production, would create in ticketing system
import random
ticket_id = f"TKT-{random.randint(1000, 9999):04d}"

valid_priorities = ['low', 'medium', 'high', 'urgent']
if priority.lower() not in valid_priorities:
priority = 'medium' # Default to medium

return {
'status': 'success',
'report': f'Support ticket {ticket_id} created with {priority} priority',
'data': {
'ticket_id': ticket_id,
'customer_id': customer_id,
'issue': issue,
'priority': priority,
'status': 'open',
'created_at': '2025-10-13T10:00:00Z',
'estimated_response': '2 hours' if priority in ['high', 'urgent'] else '24 hours'
}
}


def get_billing_history(customer_id: str) -> Dict[str, Any]:
"""
Retrieve billing history.

Args:
customer_id: Customer identifier

Returns:
Dict with billing history
"""
# Simulated billing lookup - in production, would query billing database
billing_history = {
'CUST-001': [
{'date': '2025-09-01', 'amount': 49.99, 'description': 'Monthly subscription'},
{'date': '2025-08-01', 'amount': 49.99, 'description': 'Monthly subscription'},
{'date': '2025-07-15', 'amount': 29.99, 'description': 'One-time purchase'}
],
'CUST-002': [
{'date': '2025-09-15', 'amount': 19.99, 'description': 'Basic plan'},
{'date': '2025-08-15', 'amount': 19.99, 'description': 'Basic plan'}
]
}

history = billing_history.get(customer_id, [])

if not history:
return {
'status': 'error',
'error': f'No billing history found for {customer_id}',
'report': f'No billing records found for customer {customer_id}'
}

total = sum(item['amount'] for item in history)

return {
'status': 'success',
'report': f'Found {len(history)} billing records for {customer_id}',
'data': {
'customer_id': customer_id,
'transactions': history,
'total_amount': total,
'currency': 'USD'
}
}


def process_refund(order_id: str, amount: float) -> Dict[str, Any]:
"""
Process refund (requires approval for amounts > $100).

Args:
order_id: Order identifier
amount: Refund amount

Returns:
Dict with refund status
"""
if amount > 100:
return {
'status': 'error',
'error': 'REQUIRES_APPROVAL',
'report': f'Refund of ${amount} for {order_id} needs manager approval',
'data': {
'order_id': order_id,
'amount': amount,
'status': 'pending_approval',
'approval_required': True
}
}

return {
'status': 'success',
'report': f'Refund of ${amount} approved for {order_id}. Funds will appear in 3-5 business days.',
'data': {
'order_id': order_id,
'amount': amount,
'status': 'approved',
'processing_time': '3-5 business days',
'refund_id': f'REF-{order_id}-{amount:.0f}'
}
}


def update_payment_method(customer_id: str, payment_type: str) -> Dict[str, Any]:
"""
Update stored payment method.

Args:
customer_id: Customer identifier
payment_type: New payment method type

Returns:
Dict with update confirmation
"""
# Simulated payment method update - in production, would update payment system
valid_types = ['credit_card', 'debit_card', 'paypal', 'bank_transfer']

if payment_type.lower() not in valid_types:
return {
'status': 'error',
'error': f'Invalid payment type: {payment_type}',
'report': f'Payment type must be one of: {", ".join(valid_types)}'
}

return {
'status': 'success',
'report': f'Payment method for {customer_id} updated to {payment_type}',
'data': {
'customer_id': customer_id,
'payment_type': payment_type,
'updated_at': '2025-10-13T10:00:00Z',
'verification_required': True,
'status': 'pending_verification'
}
}

Loading and Running Configuration

Process Flow:

root_agent.yaml ──► config_agent_utils.from_config() ──► Agent Instance
├── Validate YAML syntax
├── Resolve tool functions
├── Create agent with config
└── Return ready-to-use agent
# run_agent.py

"""
Load and run agent from YAML configuration.
"""

import asyncio
import os
from google.adk.agents import Runner, Session
from google.adk.agents import config_agent_utils

# Environment setup
os.environ['GOOGLE_GENAI_USE_VERTEXAI'] = '1'
os.environ['GOOGLE_CLOUD_PROJECT'] = 'your-project-id'
os.environ['GOOGLE_CLOUD_LOCATION'] = 'us-central1'


async def main():
"""Load configuration and run agent."""

# Load agent from YAML configuration
agent = config_agent_utils.from_config('root_agent.yaml')

# Create runner and session
runner = Runner()
session = Session()

# Test queries
queries = [
"I'm customer CUST-001 and I want to check my order ORD-001",
"I need help with a login error",
"I'd like a refund of $75 for order ORD-002"
]

for query in queries:
print(f"\n{'='*70}")
print(f"QUERY: {query}")
print(f"{'='*70}\n")

result = await runner.run_async(
query,
agent=agent,
session=session
)

print("RESPONSE:")
print(result.content.parts[0].text)
print(f"\n{'='*70}")

await asyncio.sleep(2)


if __name__ == '__main__':
asyncio.run(main())

Expected Output

======================================================================
QUERY: Check the status of customer CUST-001
======================================================================

RESPONSE:
Hello! I can help you check the customer status. Let me look that up for you.

Customer CUST-001 is premium member

Is there anything else I can help you with?

======================================================================

======================================================================
QUERY: What's the status of order ORD-001?
======================================================================

RESPONSE:
I'd be happy to check the status of your order. Let me look that up.

Order ORD-001 status: shipped

If you need tracking information or have any other questions about this order, just let me know!

======================================================================

======================================================================
QUERY: Can you track shipment for order ORD-001?
======================================================================

RESPONSE:
I'll help you track that shipment. Let me get the tracking details.

Tracking: UPS 1Z999AA10123456784, ETA: 2025-10-10

Your package is currently in transit and expected to arrive by October 10th, 2025. You can track it directly on the UPS website using the tracking number above.

======================================================================

4. YAML vs Python: When to Use Each

Decision Flow: YAML or Python?

Need to configure an agent?
├── Is this for rapid prototyping/testing? ──► YAML
├── Do non-technical team members need to edit? ──► YAML
├── Need version control for configurations? ──► YAML
├── Require multi-environment configs? ──► YAML
├── Need complex conditional logic? ──► PYTHON
├── Require dynamic tool selection? ──► PYTHON
├── Need custom components/callbacks? ──► PYTHON
├── Building advanced patterns (loops)? ──► PYTHON
└── Need IDE support (autocomplete)? ──► PYTHON

Use YAML Configuration When:

Rapid prototyping - Testing different agent configurations ✅ Non-technical editors - Allow team members to modify agents ✅ Configuration management - Separate config from code ✅ Multi-environment - Dev, staging, prod configurations ✅ Simple workflows - Standard agent patterns ✅ Version control - Track configuration changes easily

Use Python Code When:

Complex logic - Conditional tool selection, dynamic workflows ✅ Custom components - Custom planners, executors, callbacks ✅ Advanced patterns - Loops, complex state management ✅ Programmatic generation - Creating agents dynamically ✅ Testing - Unit tests, integration tests ✅ IDE support - Type checking, autocomplete, refactoring

Hybrid Approach (Best Practice)

Architecture: Combine YAML declarative config with Python programmatic customization.

YAML Base Config ──┐
├──► Agent Instance ──┬──► Runtime
Python Code ───────┘ │
├──► Custom Tools
├──► Dynamic Logic
└──► Runtime Adjustments
from google.adk.agents import config_agent_utils

# Load base configuration from YAML
agent = config_agent_utils.from_config('base_agent.yaml')

# Customize programmatically
agent.tools.append(custom_complex_tool)
agent.instruction += "\n\nAdditional dynamic instructions"

# Run with custom logic
if user_is_premium:
agent.tools.append(premium_tool)

runner.run(query, agent=agent)

5. Best Practices

✅ DO: Use Environment-Specific Configs

Directory Structure:

config/
├── dev/
│ ├── root_agent.yaml # Development config
│ └── secrets.yaml # Dev secrets
├── staging/
│ ├── root_agent.yaml # Staging config
│ └── secrets.yaml # Staging secrets
└── prod/
├── root_agent.yaml # Production config
└── secrets.yaml # Prod secrets
# config/dev/root_agent.yaml
name: support_agent_dev
model: gemini-2.0-flash
generate_content_config:
temperature: 0.8 # More creative for testing

# config/prod/root_agent.yaml
name: support_agent_prod
model: gemini-2.0-flash
generate_content_config:
temperature: 0.3 # More consistent for production

✅ DO: Document Configuration

# root_agent.yaml

# Customer Support Orchestrator
# Maintainer: support-team@example.com
# Last Updated: 2025-10-08
#
# This agent routes customer inquiries to specialized agents:
# - order_agent: Order management
# - technical_agent: Technical support
# - billing_agent: Payment issues

name: customer_support
model: gemini-2.0-flash

instruction: |
[Clear instruction here]

✅ DO: Validate Configuration

from google.adk.agents import config_agent_utils

def validate_config(yaml_path: str) -> bool:
"""Validate agent configuration."""

try:
agent = config_agent_utils.from_config(yaml_path)
print(f"✅ Configuration valid: {agent.name}")
return True

except Exception as e:
print(f"❌ Configuration error: {e}")
return False


# Validate before deployment
validate_config('root_agent.yaml')

✅ DO: Version Control Configuration

# .gitignore - Don't commit secrets
config/secrets.yaml
*.env

# Git commit configuration changes
git add root_agent.yaml
git commit -m "Update customer_support agent temperature to 0.5"

❌ DON'T: Hardcode Secrets

# ❌ Bad - secrets in config
tools:
- type: api
api_key: "sk-proj-abc123..." # NEVER do this

# ✅ Good - reference environment variables
tools:
- type: api
api_key: "${API_KEY}" # Load from environment

6. Advanced Configuration Patterns

Pattern 1: Conditional Sub-Agents

# Different sub-agents for different tiers
name: support_agent

sub_agents:
# Basic support (all tiers)
- name: faq_agent
model: gemini-2.0-flash
description: FAQ and basic questions

# Premium support only (filter in code)
- name: premium_support_agent
model: gemini-2.0-flash
description: Premium customer support
# Enable only for premium customers in code

Pattern 2: Configuration Inheritance

from google.adk.agents import config_agent_utils

# Load base configuration
specialized_agent = config_agent_utils.from_config('config/base.yaml')

# Create specialized variants
specialized_agent.instruction += "\n\nSpecialized for domain X"
specialized_agent.tools.append(domain_specific_tool)

Pattern 3: Dynamic Tool Registration

from google.adk.agents import config_agent_utils

# Load config
agent = config_agent_utils.from_config('root_agent.yaml')

# Add tools dynamically based on user permissions
if user.has_permission('admin'):
agent.tools.append(FunctionTool(admin_tool))

if user.has_permission('data_export'):
agent.tools.append(FunctionTool(export_tool))

7. Troubleshooting

Issue: "Configuration file not found"

Solutions:

  1. Check file path:
import os
config_path = 'root_agent.yaml'
print(f"Looking for: {os.path.abspath(config_path)}")
print(f"Exists: {os.path.exists(config_path)}")
  1. Specify absolute path:
from google.adk.agents import config_agent_utils

agent = config_agent_utils.from_config('/full/path/to/root_agent.yaml')

Issue: "Invalid YAML syntax"

Solution: Validate YAML syntax:

# Install yamllint
pip install yamllint

# Validate configuration
yamllint root_agent.yaml

Issue: "Tool function not found"

Solution: Ensure tool functions are importable:

# tools/__init__.py
from .customer_tools import (
check_customer_status,
log_interaction,
get_order_status
)

__all__ = [
'check_customer_status',
'log_interaction',
'get_order_status'
]

Summary

You've mastered YAML agent configuration:

Key Takeaways:

  • root_agent.yaml for declarative agent definitions
  • config_agent_utils.from_config() to load configurations
  • ✅ YAML for rapid prototyping and configuration management
  • ✅ Python code for complex logic and customization
  • ✅ Hybrid approach combines best of both
  • ✅ Environment-specific configs for dev/staging/prod
  • ✅ Version control for configuration tracking

Production Checklist:

  • Configuration files version controlled
  • Secrets loaded from environment variables
  • Configuration validation in CI/CD
  • Environment-specific configs (dev/staging/prod)
  • Documentation in YAML comments
  • Tool functions properly registered
  • Configuration tested before deployment
  • Backup of production configurations

Next Steps:

  • Tutorial 21: Learn Multimodal & Image Generation
  • Tutorial 22: Master Model Selection & Optimization
  • Tutorial 23: Explore Production Deployment

Resources:


🎉 Tutorial 20 Complete! You now know how to configure agents with YAML. Continue to Tutorial 21 to learn about multimodal capabilities and image generation.

💬 Join the Discussion

Have questions or feedback? Discuss this tutorial with the community on GitHub Discussions.