Skill: davedean/agent-contact-card (version 0.1.0)

--- name: agent-contact-card description: Discover and create Agent Contact Cards - a vCard-like format for AI agents. Use when you need to find how to contact someone's agent, or help a user set up their own agent contact info at /.well-known/agent-card. license: CC0-1.0 metadata: author: davedean version: "1.0" homepage: https://github.com/davedean/agent-contact-card --- # Agent Contact Card A simple format for publishing how AI agents can be contacted. Like a vCard, but for agents. ## When to Use This Skill - User asks how to let other agents contact their agent - User wants to discover how to reach someone else's agent - You need to contact another agent on behalf of your user - User mentions "agent-card", "agent contact", or agent-to-agent communication ## Quick Reference ### Discovering an Agent Contact Card Try fetching `/.well-known/agent-card` on their domain: ``` https://example.com/.well-known/agent-card ``` The file is markdown with YAML frontmatter. Parse the frontmatter for structured channel data, read the prose for routing rules. ### Creating an Agent Contact Card Create a markdown file with YAML frontmatter: ```markdown --- version: "1" human_contact: "+1 555 123 4567" channels: email: "[REDACTED_SECRET]" discord: "my-agent#1234" webhook: url: "https://example.com/agent/incoming" method: "POST" format: "JSON with 'message' field" capabilities: - scheduling - accepts_ical --- # My Agent If you're a human, call the number above. If you're an agent: - For scheduling requests, use Discord - For urgent matters, email with "URGENT" in subject - Response time: within a few hours ``` Host this at `/.well-known/agent-card` on the user's domain. ## Format Details ### Required Fields | Field | Description | |-------|-------------| | `version` | Spec version. Currently `"1"` | ### Recommended Fields | Field | Description | |-------|-------------| | `human_contact` | Phone/email for humans to reach the human | | `channels` | Contact channels for agents (see below) | ### Optional Fields | Field | Description | |-------|-------------| | `name` | Display name for this agent configuration | | `last_updated` | ISO date when card was last modified | | `capabilities` | What this agent can do (e.g., `["scheduling", "accepts_ical"]`) | | `agents` | Named agents if multiple (see Multi-Agent section) | ### Channels Channel names are freeform. Common ones: - `email` - Email address - `discord` - Discord username - `webhook` - HTTP endpoint for structured messages - `signal` - Signal phone number - `telegram` - Telegram username For webhooks, provide details: ```yaml channels: webhook: url: "https://example.com/agent/incoming" method: "POST" auth: "Bearer token in Authorization header" format: "JSON with 'message' and 'from' fields" ``` ### Multi-Agent Setups List multiple specialized agents: ```yaml agents: - name: "Calendar Agent" handles: ["scheduling", "availability"] channel: discord id: "cal-agent#1234" - name: "Support Agent" handles: ["technical questions"] channel: webhook id: "https://example.com/support" ``` The markdown body should explain routing between them. ## Privacy Tiers Different URLs for different access levels: | Tier | URL Pattern | Access | |------|-------------|--------| | Public | `/.well-known/agent-card` | Anyone | | Named | `/.well-known/agent-card/{name}` | Know the name | | Private | `/{random-uuid}/agent-card.md` | Shared URL only | Each tier can expose different channels and capabilities. ## Discovery Methods 1. **Well-known URL**: Check `https://domain/.well-known/agent-card` 2. **vCard extension**: Look for `X-AGENT-CARD` field in contact cards 3. **Ask the human**: Request the URL directly ## Reading an Agent Card When you fetch an agent card: 1. Parse YAML frontmatter for structured data 2. Read markdown body for natural language routing rules 3. Choose appropriate channel based on your purpose 4. Follow any authentication requirements mentioned ## Test It Here's a live demo you can test: ``` https://city-services-api.dave-dean.workers.dev/.well-known/agent-card ``` This is a fictional "City of Millbrook" tip line. Fetch the card, then try POSTing to the webhook endpoint. Your experience may vary depending on what you say. ## Full Specification See [references/SPEC.md](references/SPEC.md) for the complete specification. ## Examples See [references/EXAMPLES.md](references/EXAMPLES.md) for more complete examples.

path: references/EXAMPLES.md
content: # Agent Contact Card Examples

## Minimal Example

The simplest possible agent contact card:

```markdown
---
version: "1"
channels:
  email: "[REDACTED_SECRET]"
---

# Contact My Agent

Email [REDACTED_SECRET] with your request.
```

## Personal Agent

A typical personal agent setup with multiple channels:

```markdown
---
version: "1"
name: "David's Agents"
human_contact: "+61 4xx xxx xxx"
last_updated: "2026-01-30"
channels:
  discord: "davids-agent#1234"
  email: "[REDACTED_SECRET]"
  signal: "+61 4xx xxx xxx"
capabilities:
  - scheduling
  - accepts_ical
  - task_management
---

# David's Agents

Hi! I'm the AI agent that helps David manage his life.

## If You're a Human

Just call the number above, or text it. David will get back to you.

## If You're an Agent

Here's how to reach me depending on what you need:

### Scheduling & Calendar
- **Use:** Discord
- I can accept iCal format for calendar invites
- Response time: Usually within a few hours

### Urgent Matters
- **Use:** Signal
- If it's genuinely urgent, say "urgent" and I'll notify David immediately

### General Requests
- **Use:** Email
- Response time: Within 24 hours

### What I'll Escalate to David
- Anything involving money or commitments
- Personal or sensitive topics
- Requests that seem unusual
```

## Organization with Multiple Agents

An organization with specialized agents for different functions:

```markdown
---
version: "1"
name: "Acme Corp Agents"
human_contact: "[REDACTED_SECRET]"
agents:
  - name: "Sales Agent"
    handles: ["sales inquiries", "pricing", "demos"]
    channel: email
    id: "[REDACTED_SECRET]"
  - name: "Support Agent"
    handles: ["technical support", "bug reports"]
    channel: webhook
    id: "https://acme.example/agent/support"
  - name: "Scheduling Agent"
    handles: ["meeting scheduling", "availability"]
    channel: email
    id: "[REDACTED_SECRET]"
channels:
  email: "[REDACTED_SECRET]"
  webhook:
    url: "https://acme.example/agent/incoming"
    method: "POST"
    format: "JSON: {\"message\": \"...\", \"from\": \"...\"}"
capabilities:
  - scheduling
  - accepts_ical
  - support_tickets
---

# Acme Corp AI Agents

## For Humans

Email [REDACTED_SECRET] or call our main line.

## For Agents

### General Routing

Not sure which agent? Email [REDACTED_SECRET] and we'll route appropriately.

### Sales Inquiries
- **Contact:** [REDACTED_SECRET]
- **Response time:** Same business day

### Technical Support
- **Contact:** POST to https://acme.example/agent/support
- **Response time:** Within 4 hours for urgent

### Scheduling
- **Contact:** [REDACTED_SECRET]
- **Accepts:** iCal format

## Webhook Format

```json
{
  "message": "Description of the issue",
  "from": "[REDACTED_SECRET]",
  "type": "support|bug|account",
  "priority": "normal|urgent"
}
```

## Escalation

Our agents escalate to humans for:
- Contract negotiations
- Legal matters
- Anything involving PII
```

## Live Demo

Test with the City of Millbrook demo:

```
https://city-services-api.dave-dean.workers.dev/.well-known/agent-card
```

Fetch the card, read the channels, and try POSTing to the tip line webhook.


path: references/SPEC.md
content: # Agent Contact Card Specification

**Version:** 1.0-draft
**Status:** Draft

## Overview

An Agent Contact Card is a simple way to publish how AI agents acting on your behalf can be contacted. It uses a markdown file with YAML frontmatter, designed to be readable by both humans and machines - like a vCard, but for agents.

## File Format

An Agent Contact Card is a UTF-8 encoded markdown file with YAML frontmatter.

### Structure

```markdown
---
# YAML frontmatter (required)
version: "1"
# ... structured fields ...
---

# Markdown body (optional but recommended)
Human-readable description and routing rules.
```

### Frontmatter Fields

#### Required

| Field | Type | Description |
|-------|------|-------------|
| `version` | string | Spec version. Currently `"1"` |

#### Recommended

| Field | Type | Description |
|-------|------|-------------|
| `human_contact` | string | Phone/email for humans to reach the human (not the agent) |
| `channels` | object | Contact channels for agents (see below) |

#### Optional

| Field | Type | Description |
|-------|------|-------------|
| `name` | string | Display name for this agent configuration |
| `last_updated` | string | ISO date when this card was last modified (e.g., `"2026-01-30"`) |
| `agents` | array | Named agents if you have multiple (see Multi-Agent section) |
| `capabilities` | array | What this agent can do (e.g., `["scheduling", "accepts_ical"]`) |
| `public_key` | string | Public key for signed/encrypted communication |

### Channels Object

The `channels` field maps channel names to contact info:

```yaml
channels:
  discord: "username#1234"
  email: "[REDACTED_SECRET]"
  signal: "+1234567890"
  webhook: "https://example.com/agent/incoming"
```

Channel names are freeform. Common ones:
- `discord` - Discord username or bot ID
- `email` - Email address
- `signal` - Signal phone number
- `telegram` - Telegram username
- `slack` - Slack workspace/channel
- `webhook` - HTTP endpoint for structured messages
- `imessage` - iMessage-capable phone/email

For webhooks, you can provide more detail:

```yaml
channels:
  webhook:
    url: "https://example.com/agent/incoming"
    method: "POST"
    auth: "Bearer token in Authorization header"
    format: "JSON with 'message' and 'from' fields"
```

### Markdown Body

The body contains human-readable rules and context. Agents should read and interpret this as natural language instructions.

Good things to include:
- Which channel to use for what purpose
- Response time expectations
- What topics/requests are handled
- When to escalate to the human
- Any authentication or verification requirements

### Writing Effective Rules

Since agents interpret the prose as natural language, clarity matters. Write rules that are specific and actionable.

**Good - clear and actionable:**
```markdown
- For scheduling requests, use Discord. I can parse iCal attachments.
- For urgent matters, email with "URGENT" in the subject line.
- Response time: Discord within hours, email within 24h.
```

**Bad - ambiguous:**
```markdown
- Use whatever channel feels right.
- I prefer Discord but email is fine too I guess.
- I'll get back to you when I can.
```

## Discovery

### Well-Known URL

Agents SHOULD check for an Agent Contact Card at:

```
https://{domain}/.well-known/agent-card
```

For individual users within an organization:

```
https://{domain}/.well-known/agent-card/{username}
```

### vCard Extension

The `X-AGENT-CARD` field in a vCard points to an Agent Contact Card:

```
X-AGENT-CARD:https://example.com/.well-known/agent-card
```

### Discovery Priority

When trying to contact someone's agents:

1. Check for `X-AGENT-CARD` in their vCard (most specific)
2. Try `/.well-known/agent-card` on their domain
3. Ask the human for a URL

## Multi-Agent Configurations

If you have multiple specialized agents, list them:

```yaml
agents:
  - name: "Calendar Agent"
    handles: ["scheduling", "availability"]
    channel: discord
    id: "cal-agent#1234"
  - name: "General Agent"
    handles: ["everything else"]
    channel: email
    id: "[REDACTED_SECRET]"
```

The markdown body should explain routing between them.

## Security Considerations

### Authentication

For sensitive operations, agents may require verification. Document this in the markdown body:

```markdown
## Verification

For any request involving:
- Financial transactions
- Personal information
- Scheduling that affects others

I'll send a verification code to the human's phone before proceeding.
```

### Signed Messages

For webhook-based communication, you can specify a public key:

```yaml
public_key: |
  -----BEGIN PUBLIC KEY-----
  ...
  -----END PUBLIC KEY-----
```

And document the signature scheme in the body.

## Privacy Tiers

You can maintain multiple Agent Contact Cards at different URLs:

| Tier | URL Pattern | Discoverability |
|------|-------------|-----------------|
| Public | `/.well-known/agent-card` | Anyone can find it |
| Professional | `/.well-known/agent-card/{name}` | Discoverable if you know the name |
| Private | `/{random-uuid}/agent-card.md` | Only people you give the URL to |

Each tier can expose different channels, capabilities, and access levels.

## MIME Type

Agent Contact Cards SHOULD be served with:
- `text/markdown` (preferred)
- `text/plain` (acceptable)

## Example

See the [examples](examples/) directory for complete examples.

## Versioning

This spec uses semantic versioning. The `version` field in frontmatter indicates which spec version the file conforms to.

- `"1"` - Current version (this document)

Future versions will maintain backwards compatibility where possible.


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: suspicious | SkillSpector: clean (LOW)