Adding Connector
Use this skill to add connector support without bypassing Puffer's resource, subscription, auth, and workflow contracts. Prefer typed templates and protocol adapters over stringly command plumbing.
Decide The Shape
Start by choosing the smallest connector shape that satisfies the request:
- Template plus action protocol: Add or update a
ConnectorTemplatewhen the connector can authenticate, act, or subscribe through a subprocess command. Core files:crates/puffer-subscriptions/src/catalog.rs,resources/tools/connector_template.yaml, andresources/tools/connector_register.yaml. - Manifest-backed subscriber: Use
resources/subscribers/<id>/manifest.tomlwhen a reusable process should publish events for one or more connections. Seecrates/puffer-subscriber-runtime/src/manifest.rs. - Internal tool connector: Use
resources/internal_tools/<connector>.yamlplus a runtime implementation undercrates/puffer-core/runtime/claude_tools/workflow/when Puffer should expose lookup, auth, or read helpers directly to agents. - Agent proxy connector: Update
crates/puffer-subscriptions/src/proxy.rsonly when external chats should proxy into Puffer agents. - Legacy serve connector crate: Add a
crates/puffer-connector-*crate and wirecrates/puffer-cli/src/connectors.rsonly for gateway-style bot connectors started bypuffer serve.
Do not add telemetry, feedback upload, or analytics while adding a connector.
Template Contract
For built-in templates, update crates/puffer-subscriptions/src/catalog.rs:
- Add a stable kebab-case
slug. - Fill
description,skill, andbinarywith human-readable values. - Set
requires_auth,can_subscribe, andcan_proxy_agenttruthfully. - Add a deterministic default in
suggested_connection_slug. - Add action definitions with JSON schemas and explicit permission metadata.
Mark outbound side effects with
external_side_effect: true. - Keep output payloads compatible with
message_output_schema()unless the connector really needs a custom schema.
For user-defined or command-backed connectors, use the same template shape that
ConnectorTemplate returns:
{
"slug": "example-login",
"description": "Example account connector",
"skill": "example",
"binary": "example-connector",
"command": ["example-connector"],
"requires_auth": true,
"can_subscribe": true,
"actions": {}
}
Process Protocol
Command-backed connectors must follow crates/puffer-subscriptions/src/protocol.rs.
Implement these operations:
auth-ok <connection>: printtrue,false, or JSON containingokorsuccess.act <connection> <action>: read one JSON object from stdin and print either an empty success response, raw JSON output, or{"success":true,"summary":"...","output":{...}}.subscribe: read a{"op":"subscribe","connection":"...","cursor":...}line from stdin, emit JSONL frames to stdout, and handle later{"op":"ack","cursor":"...","event_id":"..."}commands.
Subscription stdout frames are one JSON object per line:
{"type":"event","id":"stable-event-id","cursor":"durable-cursor","payload":{}}
{"type":"checkpoint","cursor":"durable-cursor"}
{"type":"health","status":"ok","detail":"optional"}
Use stable event ids and cursors. Include connector-specific source ids, timestamps, sender or target ids, text, and enough context for workflow triage or monitor tasks. Never print secrets in frames, summaries, or stderr logs.
Auth And Connections
Authentication should end by recording a ConnectionCreate entry with a stable
connection slug and connector slug. Keep secrets in the user auth store,
subscriber state dir, or connector-specific private state, not in resource files
or workflow specs.
If the connector needs an interactive /connect flow, update the command helper
or internal tool to gather choices through AskUserQuestion and then register
the connection. For non-interactive auth helpers, make the helper idempotent and
safe to retry.
Add or update resources/skills/<connector>/SKILL.md when agents need operating
instructions for auth, lookup, reading messages, or sending actions.
Workflow Support
Workflow triggers require a connector that can produce events:
can_subscribe=true, and eithercommandsupportssubscribeorsubscriberpoints to a valid manifest.workflow_tools.rsandsubscription_create.rsstart subscribers for connection-backed workflows; update tests if the new connector needs a new support path.ActionSpec::ConnectorActcalls connector actions through the template action contract. Keep action inputs structured and validate them in tests.ActionSpec::TriageAgentcan consume connector events, so payloads should be compact, source-attributed, and deterministic.
Tests And Specs
Add focused tests with the code change:
- Template catalog tests for slug, default connection slug, actions, and workflow-trigger support.
- Protocol bridge tests for
auth-ok,act,subscribe, cursor ack, and malformed output handling. - Auth or
/connecttests for connection registration and secret redaction. - Internal tool tests for lookup/read helpers and schema compatibility.
- TUI or command tests when the connector appears in
/connect,/workflows,/skills, or/tasks.
Update the relevant numbered spec without overwriting old specs:
specs/puffer-subscriptions/, specs/puffer-resources/,
specs/puffer-core/, specs/puffer-cli/, or the connector crate's own
specs/<component>/ folder.
Before finishing, run targeted tests first, then broaden as risk grows. For shared connector/runtime changes, prefer:
cargo fmt --check
cargo test -p puffer-subscriptions
cargo test -p puffer-core workflow
cargo test --workspace -- --test-threads=1
Honor repo constraints: public Rust functions need docstrings, new Rust files must stay under 1000 lines, modules should stay purpose-specific, and resource provenance must remain explicit.