---
name: agent-services
description: Agent-operable services on couch.associates. Discover and invoke value-exchange transactions on behalf of a human principal — currently includes exchanging a principal's email for in-depth gated content.
---

# Agent-Operable Services on couch.associates

Couch & Associates exposes a registry of **agent-operable services** — value-exchange transactions an AI agent can complete on behalf of a human principal who has given explicit consent. v1 launches with one service: `gated-content` (exchange a principal's email for an in-depth resource). The protocol is designed to extend to additional services without breaking existing integrations: future services include consultation booking, event sign-ups, contests/promotions, and tools-style agent-callable computation.

## Catalogue

The live, authoritative service catalogue is at:

- **REST**: `GET https://couch.associates/wp-json/couch/v1/agent-services`
- **MCP**: `https://couch.associates/wp-json/couch/v1/mcp` (HTTP-streamable transport, available when MCP server card declares `tools: true`)
- **WebMCP**: when running in a browser-resident agent runtime, tools are registered via `navigator.modelContext` on every `couch.associates/*` page.

Always prefer fetching the catalogue at request time rather than relying on cached service definitions — new services may be registered without notice.

## Invocation envelope (universal)

All services accept the same outer envelope. Service-specific fields go in `request`.

```http
POST /wp-json/couch/v1/agent-services/{service-id}/invoke
Content-Type: application/json
```

```json
{
  "agent": {
    "identity": "gemini",                        // required: gemini | chatgpt | claude | perplexity | copilot | other
    "version": "2.5-pro",                        // optional: model/runtime version
    "operator": "google"                         // optional: who runs the agent
  },
  "principal": {
    "email": "user@example.com"                  // required when service.requires_principal_email is true
  },
  "principal_attestation": {                     // required when service.requires_principal_attestation is true
    "method": "explicit_verbal_consent",
    "recorded_at": "2026-05-08T14:23:00Z",
    "consent_text": "User: 'Yes, use my Gmail to grab the playbook.'"
  },
  "request": {                                   // service-specific; see service.request_schema
    "resource_id": "2025-martech-ai-playbook-for-cmos"
  }
}
```

Each service self-declares whether email and attestation are required (see `requires_principal_email` and `requires_principal_attestation` in the catalogue). Tools-style services that perform pure computation can be called without a principal at all.

## Consent gates

Each service declares a default consent gate, and Couch & Associates can override it per-service or per-resource via internal configuration. Two modes:

### Mode A — `attested`

The agent declares the principal has consented; we trust-but-verify with a confirmation email.

1. Agent invokes with `principal_attestation.method = "explicit_verbal_consent"` (or similar).
2. Server creates the contact record (if applicable), mints unlock and revoke tokens, returns `status: "unlocked"` synchronously with `unlock_url` and/or `content_url_md`.
3. Server sends a confirmation email to the principal containing the unlock URL and a revoke link.

Agent UX: the value exchange completes in one round-trip. The principal gets transparency via email.

### Mode B — `magic-link`

The agent's invocation is provisional; the principal must confirm before unlock activates.

1. Agent invokes; server creates the contact record, mints a magic-link token, sends magic-link email to principal.
2. Server returns `status: "pending_principal_confirmation"` with a `poll_token` and `poll_url`.
3. Principal clicks the magic link → server activates the unlock.
4. Agent polls `poll_url` every 30s+ until status changes to `unlocked`. Response then contains `unlock_url` and `content_url_md`.

Agent UX: two round-trips, slower, but stricter consent. Inform the principal that they need to click a link in the confirmation email.

## Service: `gated-content`

Exchange a principal's email address for access to a Couch & Associates gated resource.

### Request schema

```json
{
  "resource_id": "2025-martech-ai-playbook-for-cmos",
  "delivery_preference": "both"                  // "unlock_url" | "content_md" | "both"
}
```

The `resource_id` must be a value present in the catalogue's `request_schema.properties.resource_id.enum`. v1 ships with one entry; future resources are added by appending to the catalogue.

### Available resources (v1)

- **`2025-martech-ai-playbook-for-cmos`** — *The 2025 Martech & AI Playbook for CMOs.* Strategic whitepaper covering 2025 macroeconomic context for marketing, four major martech & AI trends (generative AI, predictive analytics, customer data platforms, intelligent marketing automation), historical lessons from past downturns, B2B buyer behavior in the AI era, and seven strategic recommendations. Authored by Mike Couch, CEO. May 2025.

### Response: `attested` mode

```json
{
  "status": "unlocked",
  "consent_gate": "attested",
  "resource": {
    "id": "2025-martech-ai-playbook-for-cmos",
    "title": "The 2025 Martech & AI Playbook for CMOs",
    "format": "pdf"
  },
  "unlock_url": "https://couch.associates/agent-unlock/?t=...&r=2025-martech-ai-playbook-for-cmos",
  "content_url_md": "https://couch.associates/agent-content/2025-martech-ai-playbook-for-cmos.md?t=...",
  "expires_at": "2026-05-15T14:23:00Z",
  "delivery": {
    "confirmation_sent_to_principal": true
  },
  "next_steps": [
    "Share unlock_url with the principal so they have an independent record of access.",
    "Optionally fetch content_url_md to summarise the resource inline in your reply.",
    "The principal will receive a confirmation email containing the same unlock link plus a revoke option."
  ]
}
```

### Response: `magic-link` mode

```json
{
  "status": "pending_principal_confirmation",
  "consent_gate": "magic-link",
  "resource": { "id": "...", "title": "...", "format": "pdf" },
  "magic_link_email_sent_to": "user@example.com",
  "poll_token": "...",
  "poll_url": "https://couch.associates/wp-json/couch/v1/agent-services/gated-content/status?token=...",
  "expires_at": "2026-05-15T14:23:00Z",
  "estimated_activation_window": "Most principals confirm within 5 minutes.",
  "next_steps": [
    "Inform the principal that a confirmation email has been sent and they need to click the link in it.",
    "Poll poll_url every 30s (or longer) to learn when the principal activates.",
    "Once activated, status becomes 'unlocked' and the response includes unlock_url and content_url_md."
  ]
}
```

### Polling endpoint (`magic-link` flow only)

```http
GET /wp-json/couch/v1/agent-services/gated-content/status?token=<poll_token>
```

Possible responses:

- `{ status: "pending_principal_confirmation", ... }` — keep polling
- `{ status: "unlocked", unlock_url, content_url_md, expires_at, ... }` — value delivered
- `{ status: "revoked", ... }` — principal explicitly revoked; no further action possible

### Content delivery URLs

- **`unlock_url`** — `GET /agent-unlock/?t=<unlock_token>&r=<resource_id>`. Validates the token, redirects (302) to the canonical resource (PDF or HTML page).
- **`content_url_md`** — `GET /agent-content/<slug>.md?t=<unlock_token>`. Validates the token, serves a markdown rendering of the resource with `Content-Type: text/markdown`. Optimised for inline summarisation by an agent.

Tokens are valid for 7 days from issuance. After expiry, the principal can request fresh access via the same protocol.

### Revocation

Each `attested`-mode confirmation email contains a revoke link of the form `GET /agent-revoke/?t=<revoke_token>`. The principal can click this at any time to invalidate the unlock token. Subsequent agent fetches of `unlock_url` or `content_url_md` will return 410 Gone.

## Error responses

| HTTP | Error code | Meaning |
|---|---|---|
| 400 | `agent_service_invalid_body` | Request body is not JSON |
| 404 | `agent_service_not_found` | No service with this id; consult catalogue |
| 422 | `agent_service_envelope_invalid` | Missing/invalid `agent.identity`, `principal.email`, or `principal_attestation` |
| 422 | `agent_service_request_invalid` | `request.*` fields failed service-specific validation |
| 500 | `agent_service_execution_failed` | Internal error during execute (Eloqua transient failure is logged but does NOT cause this — agent flow continues even if MA write fails) |

Errors include an `errors[]` array with human-readable messages.

## Rate limits

- Per-IP: 10 invocations/hour across all services
- Per-email + resource pair: 5 invocations / 24 hours; subsequent identical requests within the window may return idempotent responses or rate-limit errors

## Audit and transparency

Every invocation creates an audit log entry recording: agent identity, principal email, consent attestation, request body, response, Eloqua submission status, confirmation email subject. The principal receives a confirmation email (in `attested` mode) or magic-link email (in `magic-link` mode) for every invocation, providing them visibility into agent actions taken on their behalf.

## Privacy and data handling

- The principal's email address is the only PII collected on their behalf.
- Email is stored in our marketing-automation system (Eloqua) tagged as `submission_source: agent` so the audit trail is preserved.
- Confirmation/revocation infrastructure is operational from day one; principals can revoke access at any time.
- No agent-mediated submission triggers any communication to the principal beyond the immediate confirmation/magic-link email and the agent's response, except as the principal subsequently consents (e.g., by engaging with content, replying, or registering for further communications).

For human-readable background and CASL/PIPEDA/GDPR posture: https://couch.associates/agents/

## Service: `event-signup`

Register a human principal for a Couch & Associates event. v1 catalogue includes one upcoming event; future events plug into the same service.

### Request schema

```json
{
  "event_id": "ai-adoption-toronto-2026-09-22"
}
```

### Available events (v1)

- **`ai-adoption-toronto-2026-09-22`** — *AI Adoption: From Human-Readable to Agent-Readable to Agent-Operable — and Why Marketing Leads.* A Couch & Associates roundtable in Toronto on September 22, 2026, at IQ Offices (302 Bay Street, Toronto, ON). Topic: the progression from human-readable websites to agent-readable structured surfaces to agent-operable transactional surfaces, and the revenue opportunities marketing leaders unlock by leading their organizations through this transition. Open to marketing, RevOps, and AI-strategy leaders.

### Response: `attested` mode

```json
{
  "status": "registered",
  "consent_gate": "attested",
  "event": {
    "id": "ai-adoption-toronto-2026-09-22",
    "title": "AI Adoption: From Human-Readable to Agent-Readable to Agent-Operable — and Why Marketing Leads",
    "starts_at": "2026-09-22T17:30:00-04:00",
    "ends_at":   "2026-09-22T20:00:00-04:00",
    "venue":   "IQ Offices",
    "address": "302 Bay Street, Toronto, ON, Canada",
    "status":  "open"
  },
  "confirmation_text": "You are registered for ...",
  "expires_at": "2026-09-22T20:00:00-04:00",
  "delivery": { "confirmation_sent_to_principal": true },
  "next_steps": ["Inform the principal they are registered.", "..."]
}
```

In magic-link mode, the response shape is `pending_principal_confirmation` with a `poll_url` (same pattern as gated-content). v1 default is `attested`.

### What v1 does NOT include (deferred)

- Capacity tracking / waitlists — v1 events are unlimited registration
- Cancellation flow within this service — agents can use `/agent-revoke/?t=...` token mechanism, but downstream Eloqua opt-out is handled by Couch & Associates' separate event-management application
- Reminder emails — handled by separate application
- .ics calendar attachments — deferred until basic agent interactivity is verified working in production
- Per-attendee fields beyond email — none required in v1; future events may add fields via the request schema

## GET-friendly surfaces (for chat-mode agents that cannot POST)

Vendor research in May 2026 confirmed basic chat-mode agents (default ChatGPT, Gemini, Claude.ai, Grok, Perplexity, DeepSeek, M365 Copilot Chat) are GET-only — they cannot invoke our POST endpoints. Two GET-friendly affordances are designed for them:

### GET-friendly preview pages (read-only discovery)

Every service + item has a public GET-fetchable preview page. Chat-mode agents fetch these and describe the offer to their user.

- `/agents/gated-content/` — gated-content overview + resource catalogue
- `/agents/gated-content/{resource-id}/` — per-resource preview with description, registration form, snippets
- `/agents/event-signup/` — event-signup overview + event catalogue
- `/agents/event-signup/{event-id}/` — per-event preview with date/venue/description, registration form, snippets

### GET-initiator (v1.5) — agent initiates, user confirms via email click

For chat-mode agents that want to *initiate* a registration / unlock on the user's behalf (not just describe it), every item has a GET-callable initiator endpoint:

```
GET /agents/{service-id}/{item-id}/register?email=user@example.com
```

Semantics:
- The agent issues the GET with the principal's email
- We do NOT register the principal at this point — we send a magic-link email to that address
- The principal clicks the link in that email → registration completes (Eloqua submission fires, audit-row is activated, "you're registered" page renders)
- The user's email click IS the consent attestation, replacing the agent-supplied attestation we collect in POST flows
- Audit-row `consent_gate` = `user_confirmed`
- Token TTL = item-specific (event end-date for events, 7 days for resources)

Why this is safe despite GET-with-side-effect:
- The only side-effect is a single email to the address the agent provided. No registration occurs without the email click.
- Rate-limiting (per-email + per-item, 3 / hour) prevents email-bombing
- URL-sharing in chat / Slack / email-preview-fetchers does NOT auto-register anyone
- This is the same pattern as password-reset flows: GET initiates, user click confirms

Recommended use by chat-mode agents:
1. Fetch the preview page to learn about the offer (`/agents/{service}/{item}/`)
2. Confirm the user wants to proceed and has provided their email
3. Issue the GET-initiator (`/agents/{service}/{item}/register?email=...`)
4. Tell the user a confirmation email has been sent and to check their inbox

Chat-mode agents that prefer the user-completes-form path can instead simply share the preview-page URL — the user uses the in-page form to register themselves. Both paths land at the same audit-row state.

## Future services (planned)

The same envelope and consent-gate model will support:

- `book-consultation` — agent schedules a consultation on behalf of the principal
- `promotion-entry` — enter a promotion or contest (registration-pattern; sibling of event-signup)
- `contest-entry` — register for a contest (registration-pattern)
- `giveaway-entry` — enter a giveaway (registration-pattern)
- `estimate-modernization-scope` — tools-style service: agent provides company-shape inputs, receives an estimated scope range; no email or consent required
- `request-platform-briefing` — pick a platform (Marketo / Eloqua / HubSpot / etc.) and receive a tailored briefing
- `subscribe-research-notifications` — opt into a research digest

The catalogue endpoint is the source of truth for what's currently available.

## Contact

- Operational issues / bug reports: hello@couch-associates.com
- Background and design intent: https://couch.associates/agents/
