Messaging Skills

Email

Metadata middleware that starts email listeners for inbound email (delivered by SES to S3), parses MIME, and dispatches to skills. Delegates polling to email-listen-ses via callback ref.

metadata:
  email:
    region: us-east-1
    bucket: my-email-inbox
    prefix: incoming/
    from: agent@mydomain.com
    allowed-senders: [alice@mydomain.com]
    poll-interval: 30s
    routes:
      - ref: handle-support
        from: "*@example.com"
        subject: "support*"

Individual skills can also declare themselves as email endpoints using route: (singular) — the ref is implicit:

# In a handler skill's own metadata
metadata:
  email:
    route:
      from: "*@example.com"
      subject: "support*"

The middleware pushes a gateway via setGateway() before dispatching, so gateway-send replies via email automatically. Inbound messages emit gateway-message events for observation (see Events). After processing, the S3 object is deleted.

When open: true is set in the email config, the gateway exposes send/receive defaults as overridable schema properties. The agent sees the current conversation's defaults (recipient, sender, subject) in the gateway-send schema and can override them to contact different users or customize delivery. Without open, the gateway locks send/receive to the current conversation — the agent always replies to the original sender with the original subject.

Tools: email-send (send via SES), email-receive (wait for next inbound message), email-setup (provision email infrastructure for the configured route).

email-setup

Set up email infrastructure for the configured provider. Creates SES resources (receipt rules, S3 bucket policies) needed for inbound email.

agent-apps email-setup                          # Set up using top-level config
agent-apps email-setup --arg name=work-inbox  # Set up a specific route

Arguments: name (route name, searches routes by name then falls back to top-level config), provider (email provider, defaults to config or ses).

See Email Agent Tutorial for full setup.

Slack

Metadata middleware that connects to Slack via Socket Mode.

metadata:
  slack:
    app-token: xapp-1-...
    bot-token: xoxb-...
    allowed-users: [U01ABC123]
    routes:
      - ref: handler-skill
        type: dm

Individual skills can also declare themselves as Slack endpoints using route: (singular) — the ref is implicit:

# In a handler skill's own metadata
metadata:
  slack:
    route:
      type: dm

Use environment variable overrides to avoid hardcoding tokens: AGENT_APPS_LOCAL_SLACK__APP_TOKEN=xapp-...

Socket Mode connects outbound — no inbound ports needed. The middleware pushes a gateway via setGateway() so trust prompts and gateway-send calls appear as thread replies. Inbound messages emit gateway-message events for observation.

When open: true is set in the slack config, the gateway exposes send/receive defaults as overridable schema properties. The agent can override the channel, thread, or other delivery parameters instead of being locked to the current conversation thread.

Tools: slack-send (post to channel/thread), slack-receive (wait for next message).

See Slack Bot Tutorial for Slack app setup.

Webhook

Metadata middleware that receives Standard Webhooks with HMAC signature verification, timestamp replay protection, and message deduplication.

metadata:
  webhook:
    routes:
      - path: /hooks/github
        secret: whsec_...
        ref: on-push

Individual skills can also declare themselves as webhook endpoints using route: (singular) — the ref is implicit:

# In a handler skill's own metadata
metadata:
  webhook:
    route:
      path: /hooks/github
      secret: whsec_...

Use environment variable overrides to avoid hardcoding secrets: AGENT_APPS_LOCAL_WEBHOOK__ROUTES__0__SECRET=whsec_...

Valid payloads are routed to the matching skill. Webhooks are fire-and-forget — there is no reply channel.

Roles

Identity-based metadata injection. Matches the current user's identity against glob patterns and injects metadata keys as middleware uniformly.

metadata:
  roles:
    key: "nonlocals.gateway.id"
    rules:
      - match: "*@mycompany.com"
        name: admins
        metadata:
          frontmatter: { allowed-tools: "*" }
          trust: { rules: "#meta-internal($policy=allow) *", store: file }
      - match: "*"
        name: everyone
        metadata:
          frontmatter: { allowed-tools: "file-read file-list" }

The key is resolved via pathGet — any path into ctx works (e.g., nonlocals.gateway.id, nonlocals.request.headers.x-user-id). Match patterns support globs. Every metadata key in a matched entry is injected as middleware: frontmatter for allowed-tools overrides, trust for per-user trust rules, gateway for reply-to overrides.

roles-list lists configured role entries and their match patterns.

Auth Tokens

Token-based authentication for API access. Create and revoke bearer tokens mapped to identities. Tokens are stored in the auth profile's token store.

auth-token-create

Create a new auth token mapped to an identity.

agent-apps auth-token-create --arg identity=user@example.com
# Returns: { token: "aa-tok-...", identity: "user@example.com" }

Arguments: identity (required — identity to associate), name (verify entry name). Returns { token, identity }.

auth-token-revoke

Revoke an existing auth token.

agent-apps auth-token-revoke --arg token=aa-tok-...

Arguments: token (required — token to revoke), name (verify entry name).

Ask AI