Surface 06 · CanaryAgent
Connect an agent
CanaryAgent adds heartbeat monitoring and skill scans to your agents. Post a heartbeat from your agent's loop, and submit each skill's code for a scan before it ships:
Heartbeats build a timeline per agent. A scheduled check runs every two minutes and flags any agent whose last heartbeat is older than five minutes — so a stopped agent surfaces within a few minutes of going quiet, not the instant it stops. Silent-agent alerts go to every channel on the account — built-in Telegram, built-in email, and every enabled Slack, Discord and signed-webhook channel — through the same shared dispatcher CanaryShield and CanaryHoneypot use, each delivery isolated so one failing channel never blocks the rest. A skill scan that comes back HIGH or CRITICAL raises its own alert down the same path. While alerts are paused, both built-in paths skip.
Get an API key
Both calls above authenticate with a workspace API key sent in the X-API-Key header. Mint one in the app — Settings → API keys → Generate API key — on any plan, Free included. The full key is shown once, at creation, so copy it off that screen, keep it server-side and export it as CV_KEY. Five active keys per account, and a leaked one is revoked from the same card while it is still on screen.
You don't have to write the client yourself. The CanaryAgent console has a Download canary_middleware.py button that hands you a ready-made Python client: it posts heartbeats from a background thread via start_heartbeat() and wraps the CanaryShield and CanaryAudit calls. It reads CANARY_HEARTBEAT_URL, CANARY_SHIELD_URL, CANARY_AUDIT_URL, CANARY_USER_ID and CANARY_API_KEY from the environment, and the console prints the matching .env block next to the button. It does not scan skills — run scans from the console or the endpoint above.
Read the timeline
GET /canaryagent/timeline/{user_id} returns the whole agent view for one workspace. It takes the same X-API-Key header (a session JWT in Authorization: Bearer works too), and the id in the path must be the caller's own user — another workspace's id returns 403.
Every query parameter is optional. agent_id and action_type match exactly; from_date and to_date take YYYY-MM-DD and are inclusive at both ends; limit defaults to 50 and accepts 1–500. They filter entries only — agents covers every agent that has ever sent a heartbeat, and skill_scans is always the 20 most recent scans.
count is the number of entries in this response, not the total that matched. entries are CanaryAudit records — the actions your agent logged to /canaryaudit/log. agents is derived from the latest heartbeat per agent: status reads online while a heartbeat has arrived in the last two minutes and silent after that, and actions_today counts audit records logged since midnight UTC.
The default view shows only your own agents' actions. audit_logs is shared with the canary tripwire, which seals threat events into it under agent_id=canary-tripwire and action_type=canary.tripwire_event. Those are not CanaryAgent activity, so they are excluded from entries by default — pass ?agent_id=canary-tripwire explicitly to read them.
Skill scan limits
Heartbeats do not spend plan quota. Skill scans do: agent_skill_scans_per_month allows 5 a month on Free, 50 on Shield, 500 on Pro and 1,500 on Enterprise, and a scan past that answers a structured 402 naming the metric, your plan and your reset date.
A shorter per-account daily allowance sits underneath it — 3 scans a day on Free, 10 on Shield, 40 on Pro and 100 on Enterprise — so a CI job that queues a month's worth of scans in one afternoon is refused long before the monthly quota runs out. The daily 402 names the same metric, with resets_at set to the next UTC day. This meter fails closed: if your usage cannot be checked the scan answers 503 with daily_quota_unavailable rather than running unchecked.
A per-minute burst limit sits above both: 3 scans a minute on Free, 10 on Shield, 30 on Pro and 60 on Enterprise. It answers 429 with retry_after_seconds and a Retry-After header rather than a 402, and the burst check runs before either meter, so a scan it turns away spends no quota. On every plan this figure is at or below the daily one — the two are equal on Free and Shield — so a CI job firing scans back to back meets the 429 first, and the daily 402 only once the minute has rolled over.