Skip to content

Latest commit

 

History

History
341 lines (272 loc) · 8.64 KB

File metadata and controls

341 lines (272 loc) · 8.64 KB

Commune Skill

Send and receive email with AI agents using the Commune API.

What Commune Does

Commune gives AI agents a real email address and manages the full email lifecycle:

  • Send email — DKIM-signed delivery, rate limiting, bounce tracking
  • Receive email — webhooks with parsed content, spam scoring, prompt injection detection
  • Thread email — automatic conversation threading via RFC 5322 Message-ID headers
  • Extract structured data — JSON schema → LLM extraction on every inbound email
  • Manage attachments — upload, send, download files with antivirus scanning
  • Monitor deliverability — bounce rates, complaint rates, suppression lists via API

API Base URL

https://api.commune.email

Authentication

All requests require a Bearer token:

Authorization: Bearer comm_...

Get an API key at https://commune.email/dashboard/api-keys

Alternatively, use agent authentication (Ed25519 challenge-response) to register and authenticate without human intervention. See https://commune.email/agent-auth

Quick Start (3 steps)

Step 1: Create an inbox

curl -X POST https://api.commune.email/v1/inboxes \
  -H "Authorization: Bearer comm_..." \
  -H "Content-Type: application/json" \
  -d '{"local_part": "support"}'

Response:

{
  "data": {
    "id": "inbox_abc123",
    "localPart": "support",
    "address": "support@commune.email",
    "domainId": "d_xyz"
  }
}

Step 2: Send an email

curl -X POST https://api.commune.email/v1/messages/send \
  -H "Authorization: Bearer comm_..." \
  -H "Content-Type: application/json" \
  -d '{
    "to": "user@example.com",
    "subject": "Hello",
    "text": "Message from my agent.",
    "html": "<p>Message from my agent.</p>"
  }'

Response:

{
  "data": {
    "id": "msg_xyz",
    "thread_id": "thread_abc"
  }
}

Step 3: Receive replies via webhook

Set a webhook on the inbox:

curl -X PUT https://api.commune.email/v1/domains/DOMAIN_ID/inboxes/INBOX_ID \
  -H "Authorization: Bearer comm_..." \
  -H "Content-Type: application/json" \
  -d '{
    "webhook": {
      "endpoint": "https://your-server.com/webhook/email",
      "events": ["inbound"]
    }
  }'

Webhook payload:

{
  "domainId": "d_abc",
  "inboxId": "inbox_xyz",
  "inboxAddress": "support@commune.email",
  "message": {
    "message_id": "msg_001",
    "thread_id": "thread_abc",
    "direction": "inbound",
    "content": "Hi, I need help.",
    "participants": [
      { "role": "sender", "identity": "user@example.com" },
      { "role": "to", "identity": "support@commune.email" }
    ],
    "metadata": {
      "subject": "Re: Hello",
      "created_at": "2026-02-24T10:00:00Z"
    },
    "attachments": []
  },
  "security": {
    "spam": { "checked": true, "score": 1.2, "flagged": false },
    "prompt_injection": { "checked": true, "detected": false, "risk_level": "none" }
  }
}

SDK Usage

TypeScript

import { CommuneClient } from 'commune-ai';

const commune = new CommuneClient({ apiKey: process.env.COMMUNE_API_KEY });

// Create inbox
const inbox = await commune.inboxes.create({ localPart: 'support' });

// Send email
const result = await commune.messages.send({
  to: 'user@example.com',
  subject: 'Hello',
  text: 'Message from my agent.',
});

// Reply in thread
await commune.messages.send({
  to: 'user@example.com',
  subject: 'Re: Hello',
  text: 'Here is my reply.',
  thread_id: result.thread_id,
});

// List threads
const { data: threads } = await commune.threads.list({ inbox_id: inbox.id });

// Read thread messages
const messages = await commune.threads.messages(threads[0].thread_id);

Python

from commune import CommuneClient

client = CommuneClient(api_key="comm_...")

# Create inbox
inbox = client.inboxes.create(local_part="support")

# Send email
result = client.messages.send(
    to="user@example.com",
    subject="Hello",
    text="Message from my agent.",
)

# Reply in thread
client.messages.send(
    to="user@example.com",
    subject="Re: Hello",
    text="Here is my reply.",
    thread_id=result.thread_id,
)

# List threads
threads = client.threads.list(inbox_id=inbox.id)

# Read thread messages
messages = client.threads.messages(threads.data[0].thread_id)

MCP Server

Add to Claude Desktop / Cursor / Windsurf config:

{
  "mcpServers": {
    "commune": {
      "command": "uvx",
      "args": ["commune-mcp"],
      "env": {
        "COMMUNE_API_KEY": "comm_..."
      }
    }
  }
}

Key API Endpoints

Method Endpoint Description
POST /v1/inboxes Create an inbox
GET /v1/inboxes List all inboxes
GET /v1/inboxes/:id Get an inbox
PUT /v1/domains/:domainId/inboxes/:id Update inbox (webhook, extraction schema)
POST /v1/messages/send Send an email
GET /v1/messages List messages
GET /v1/threads List conversation threads
GET /v1/threads/:id/messages Get messages in a thread
POST /v1/attachments/upload Upload an attachment
GET /v1/attachments/:id Download an attachment
GET /v1/domains List domains
POST /v1/domains Add a custom domain

Structured Data Extraction

Configure a JSON schema to automatically extract structured data from every inbound email:

await commune.inboxes.setExtractionSchema({
  domainId: 'DOMAIN_ID',
  inboxId: inbox.id,
  schema: {
    name: 'support_ticket',
    description: 'Extract ticket details from customer emails',
    enabled: true,
    schema: {
      type: 'object',
      properties: {
        order_number: { type: 'string', description: 'Order reference number' },
        intent: {
          type: 'string',
          enum: ['billing', 'technical', 'general', 'complaint', 'cancellation'],
        },
        urgency: { type: 'string', enum: ['low', 'medium', 'high'] },
        summary: { type: 'string', description: 'One-line summary' },
      },
    },
  },
});

Extracted data appears in message.metadata.extracted_data and in the extractedData field of webhook payloads.

Security Context

Every inbound email is automatically:

  • Spam-scored (0-10 scale, flagged if > 5)
  • Prompt injection-detected (risk levels: none, low, medium, high, critical)

The security context is included in every webhook payload:

{
  "security": {
    "spam": {
      "checked": true,
      "score": 2.1,
      "flagged": false,
      "reasons": []
    },
    "prompt_injection": {
      "checked": true,
      "detected": true,
      "risk_level": "high",
      "patterns": ["system_override", "ignore_instructions"]
    }
  }
}

Always check security.prompt_injection.risk_level before acting on inbound email content in agentic systems.

Webhook Verification

Webhooks are signed with HMAC-SHA256:

x-commune-signature: v1=5a3f2b8c...
x-commune-timestamp: 1708347600000

Verify: HMAC-SHA256(webhookSecret, "{timestamp}.{rawBody}")

Agent Authentication (Passwordless)

For agents that need to register themselves without human intervention:

  1. Generate Ed25519 keypair locally
  2. POST to /v1/auth/agent-register with public key and agent purpose
  3. Server returns a natural-language challenge
  4. Sign the challenge response with private key
  5. POST to /v1/auth/agent-verify — receive agentId and auto-provisioned inbox

Full spec: https://commune.email/agent-auth

Rate Limits

Plan Daily emails Inboxes
Free 50 1
Agent Pro 500 5
Business 2,000 20
Enterprise Custom Custom

Requests: 10/second per API key. Headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.

Error Format

{
  "error": {
    "message": "Rate limit exceeded",
    "code": "RATE_LIMIT_EXCEEDED"
  }
}

Common codes: RATE_LIMIT_EXCEEDED (429), INVALID_API_KEY (401), INBOX_NOT_FOUND (404), SENDING_PAUSED (503 — inbox health issue), PLAN_UPGRADE_REQUIRED (403).

Best Practices for AI Agents

  1. One inbox per agent or campaign — isolates sender reputation and reply routing
  2. Check prompt injection score before actingsecurity.prompt_injection.risk_level
  3. Use thread_id when replying — keeps conversations threaded correctly
  4. Store thread_id after sending — needed to associate future replies with the original send
  5. Monitor bounce rate — if > 5%, stop sending and review list quality
  6. Use extraction schemas — let Commune extract structured data, don't parse email body yourself
  7. Verify webhook signatures — all inbound email is authenticated via HMAC
  8. Start with shared domain — use commune.email domain for testing, add custom domain for production