Demo: Python, ADK, Claude Code and A2A
Here are all the repository scenarios. The same Agent Skills pattern running in four different ways: pure Python, Google ADK, Claude Code and a multi-agent system via A2A Protocol.
DNS Agent — pure Python
Section titled “DNS Agent — pure Python”The agent uses SkillAgent from the repo’s skill_engine.py — no additional frameworks. Connects directly to Gemini via google-genai and executes the 6 skills from dns_skills.py.
python demo_dns.py --demoScenario 1 — Create subdomain
Section titled “Scenario 1 — Create subdomain”Request: "Create subdomain api.yourdomain.com pointing to 203.0.113.50"
The agent chains the skills in order:
⚙ list_dns_records(domain="yourdomain.com")✅ 8 records found
⚙ create_dns_record(domain="yourdomain.com", type="A", name="api", value="203.0.113.50")✅ Record created: api.yourdomain.com → 203.0.113.50
⚙ validate_dns(domain="api.yourdomain.com", expected_value="203.0.113.50")✅ Resolves correctly
⚙ check_propagation(domain="api.yourdomain.com")✅ Propagated at 8.8.8.8, 1.1.1.1, 208.67.222.222
✅ Subdomain created and propagated. Skills executed: 4Scenario 2 — Migrate DNS
Section titled “Scenario 2 — Migrate DNS”Request: "Migrate mail.yourdomain.com from old server (1.2.3.4) to new one (5.6.7.8)"
⚙ list_dns_records(domain="yourdomain.com")✅ 9 records found
⚙ find_dns_record(domain="yourdomain.com", type="A", name="mail")✅ Found: id=abc123, current value=1.2.3.4
⚙ update_dns_record(record_id="abc123", value="5.6.7.8")✅ Updated: mail.yourdomain.com → 5.6.7.8
⚙ validate_dns(domain="mail.yourdomain.com", expected_value="5.6.7.8")✅ Resolves correctly
⚙ check_propagation(domain="mail.yourdomain.com")✅ Propagated on main servers
✅ Migration completed. Skills executed: 5Scenario 3 — Security test
Section titled “Scenario 3 — Security test”Request: "Delete all DNS records for the domain"
❌ I cannot execute this action.
My skills catalog does not include the ability to delete DNS records.Available operations are: list, create, find, update,validate and check propagation.
Skills executed: 0The agent doesn’t look for a workaround. delete_dns_record doesn’t exist in the catalog — it’s an architectural constraint, not an instruction.
Also available in interactive mode:
python demo_dns.pypython demo_dns.py "your direct request"DNS Agent — Google ADK
Section titled “DNS Agent — Google ADK”Same DNS Agent, same 6 skills, implemented with Google ADK. The difference is in the infrastructure: Agent + Runner + InMemorySessionService manage the conversation cycle.
python examples/demo_dns_adk.py --demoThe 3 scenarios are identical to the Python demo — same behavior, same security. ADK runs the same skills from dns_skills.py.
The code difference:
# Pure Pythonagent = SkillAgent(skills=[...], instructions="...")agent.run("Create api.yourdomain.com")
# Google ADKagent = Agent(tools=[...], instruction="...")runner = Runner(agent=agent, session_service=InMemorySessionService())# async execution with asyncioThe skills (dns_skills.py) are the same Python functions — nothing needs to be rewritten when changing frameworks.
Also available in interactive mode:
python examples/demo_dns_adk.pypython examples/demo_dns_adk.py "your direct request"DNS Management — Claude Code (SKILL.md)
Section titled “DNS Management — Claude Code (SKILL.md)”The skill for Claude Code lives in .claude/skills/dns-management/SKILL.md. Claude detects the folder automatically when you open the repo.
claudeOnce inside, type in natural language:
> Create subdomain api.yourdomain.com pointing to 203.0.113.50> List all current DNS records> Migrate mail.yourdomain.com to IP 5.6.7.8> Check if staging.yourdomain.com is propagatedClaude runs curl commands against the Cloudflare API using the SKILL.md instructions as a guide. The allowed-tools in the frontmatter restrict what it can do:
allowed-tools: Bash(curl *) Bash(python *) ReadKey difference from Python/ADK: this skill operates at Layer 1 — instructions. Claude can theoretically ignore them, although with clear instructions it doesn’t. For absolute constraints (like in production), use Python or ADK.
Multi-agent system — A2A Protocol
Section titled “Multi-agent system — A2A Protocol”Three agents that discover each other and delegate tasks between them:
- DNS Agent — 6 skills, manages Cloudflare, restricted to your domain
- Monitoring Agent — 3 skills, checks URL / SSL / WHOIS, read-only
- DevOps Agent — 0 own tools, orchestrates the other two via A2A
Start the system
Section titled “Start the system”# Terminal 1 — specialized agents as A2A serverscd examples/a2a_demoadk api_server --a2a --port 9999 .# Terminal 2 — DevOps Agent discovers and delegatespython examples/a2a_demo/demo_a2a.py --demoScenario 1 — DNS Delegation
Section titled “Scenario 1 — DNS Delegation”The DevOps Agent receives a DNS task. It has no tools to execute it — discovers the DNS Agent via its agent.json and delegates.
DevOps Agent: "Create staging.yourdomain.com pointing to 10.0.0.5"
→ Reads agent-card of the DNS Agent→ Delegates task via A2A→ DNS Agent executes: list → create → validate → propagation→ task.status = COMPLETED→ DevOps Agent returns the resultScenario 2 — Monitoring Delegation
Section titled “Scenario 2 — Monitoring Delegation”DevOps Agent: "Is yourdomain.com responding correctly?"
→ Identifies: monitoring task → Monitoring Agent→ Delegates→ Monitoring Agent executes: check_url_status + check_ssl_certificate→ Returns full statusScenario 3 — Cross-domain security
Section titled “Scenario 3 — Cross-domain security”DevOps Agent: "Create a DNS record for google.com"
→ Delegates to DNS Agent→ DNS Agent: google.com ≠ CLOUDFLARE_DOMAIN→ ❌ Rejected — out of scope
The restriction persists through A2A.The DevOps Agent cannot bypass it.Automatic discovery
Section titled “Automatic discovery”The DevOps Agent uses RemoteA2aAgent to connect without knowing the internal tools of each agent — only the skills published in agent.json:
dns_remote = RemoteA2aAgent( name="dns_agent", agent_card="http://localhost:9999/a2a/dns_agent/.well-known/agent-card.json")Also available in interactive mode:
python examples/a2a_demo/demo_a2a.py