Agent Skills Technical Guide: Architecture and Patterns
For the conceptual introduction with video, visit the Agent Skills guide.
Concept
Section titled “Concept”An Agent Skill is a scoped, reusable and safe capability that an agent can invoke. The agent reasons freely with Gemini, but can only execute what its skills allow. If a skill doesn’t exist, the action is architecturally impossible.
Term distinction
Section titled “Term distinction”| Term | Level | In this repo |
|---|---|---|
| Skill (pattern) | Design | Universal idea — separate reasoning from execution |
| Tool / Function | Execution | Python function registered in SkillAgent or ADK |
| Claude Skill (SKILL.md) | Knowledge | .claude/skills/dns-management/ folder |
| AgentSkill (A2A) | Discovery | Declaration in agent.json for inter-agent discovery |
The two layers of an agent
Section titled “The two layers of an agent”| Layer | What it is | How it’s implemented here |
|---|---|---|
| Layer 1 — Instructions | System prompt, markdown guides | instructions= in SkillAgent, SKILL.md in Claude Code |
| Layer 2 — Capabilities | Registered tools (executable functions) | skills=[...] list in SkillAgent, tools=[...] in ADK |
Layer 1 guides reasoning — the agent can ignore it. Layer 2 is a real constraint — if the tool doesn’t exist, the action is impossible.
skill_engine.py — Universal engine
Section titled “skill_engine.py — Universal engine”SkillAgent is the base class that connects Gemini with the skills catalog using automatic_function_calling.
Constructor:
agent = SkillAgent( skills=[list_dns_records, create_dns_record, ...], # Layer 2: executable functions instructions="...", # Layer 1: system prompt model="gemini-2.5-flash", # default name="DNS Agent")| Parameter | Type | Description |
|---|---|---|
skills | list[callable] | Python functions the agent can invoke |
instructions | str | System prompt — guides reasoning |
model | str | Gemini model. Default: gemini-2.5-flash |
name | str | Agent name for terminal output |
Methods:
agent.run("Create api.nicolasneira.dev pointing to 203.0.113.50")# → Gemini reasons, executes chained skills, returns final response
agent.show_catalog()# → Lists available skills with their docstringsInternal flow:
User → Gemini (reasons) → SkillAgent (searches catalog) → Python function (executes) → Gemini (interprets result) → Final responseMaximum 20 function calls per request. Each call is shown in the terminal with ✅/⚠️/❌.
dns_skills.py — 6 DNS Skills
Section titled “dns_skills.py — 6 DNS Skills”Skills against the Cloudflare API. Requires CLOUDFLARE_API_TOKEN, CLOUDFLARE_ZONE_ID and CLOUDFLARE_DOMAIN in .env.
list_dns_records(domain)
Section titled “list_dns_records(domain)”Lists all active DNS records for the domain.
list_dns_records("nicolasneira.dev")# → List of records with id, type, name, value, TTLcreate_dns_record(domain, type, name, value)
Section titled “create_dns_record(domain, type, name, value)”Creates a new DNS record. Only accepts safe types.
create_dns_record( domain="nicolasneira.dev", type="A", # Only: A, CNAME, MX, TXT name="api", value="203.0.113.50")Rejected types: NS, SOA, SRV — the skill validates internally and rejects them.
find_dns_record(domain, type, name)
Section titled “find_dns_record(domain, type, name)”Finds a specific record and returns its record_id (needed to update).
find_dns_record("nicolasneira.dev", "A", "mail")# → { "record_id": "abc123", "value": "1.2.3.4", ... }update_dns_record(record_id, value)
Section titled “update_dns_record(record_id, value)”Updates the value of an existing record using its record_id.
update_dns_record(record_id="abc123", value="5.6.7.8")validate_dns(domain, expected_value)
Section titled “validate_dns(domain, expected_value)”Validates that the DNS record resolves to the expected value.
validate_dns("api.nicolasneira.dev", "203.0.113.50")# → ✅ Resolves correctly / ❌ Not resolving yetcheck_propagation(domain)
Section titled “check_propagation(domain)”Checks propagation across multiple public DNS servers (Google, Cloudflare, OpenDNS).
check_propagation("api.nicolasneira.dev")# → Status at 8.8.8.8, 1.1.1.1, 208.67.222.222Skills that DON’T exist (design constraint):
- ❌
delete_dns_record— cannot delete - ❌
modify_nameservers— cannot change nameservers - ❌
create_for_other_domain— restricted to the configured zone
monitoring_skills.py — 3 Monitoring Skills
Section titled “monitoring_skills.py — 3 Monitoring Skills”Read-only skills. No API keys required — uses public HTTP, SSL and WHOIS.
check_url_status(url)
Section titled “check_url_status(url)”HTTP GET to the URL. Returns status code, response time and relevant headers.
check_url_status("https://nicolasneira.com")# → { "status": 200, "response_time_ms": 234, "server": "cloudflare" }check_ssl_certificate(domain)
Section titled “check_ssl_certificate(domain)”Queries the SSL certificate. Returns issuer, expiration date and days remaining.
check_ssl_certificate("nicolasneira.com")# → { "issuer": "Let's Encrypt", "expires": "2025-06-01", "days_remaining": 87 }check_domain_whois(domain)
Section titled “check_domain_whois(domain)”Queries WHOIS. Returns registrar, nameservers and domain expiration date.
check_domain_whois("nicolasneira.com")# → { "registrar": "Cloudflare, Inc.", "expires": "2026-01-15", ... }Skills that DON’T exist (design constraint):
- ❌
restart_service— observes only, does not modify - ❌
send_alert— no notification capability - ❌
modify_config— zero writes
Security patterns
Section titled “Security patterns”Security by SCOPE — DNS Agent
Section titled “Security by SCOPE — DNS Agent”The agent is restricted to the domain configured in CLOUDFLARE_DOMAIN. Any request about another domain is rejected in the instructions (Layer 1) and in the skill’s internal validations (Layer 2).
# If the user asks: "Create a record for google.com"# The skill validates domain == CLOUDFLARE_DOMAIN → rejectsSecurity by CAPABILITY — Monitoring Agent
Section titled “Security by CAPABILITY — Monitoring Agent”The agent can observe any domain without scope restriction, but has no write skills. Security comes from the absence of capability, not from instructions.