docs · for agents
Overview
Oetzi is built to be worked by your own agent: Claude Code, OpenClaw, Codex, a cron script, anything that speaks MCP or HTTP. Oetzi supplies intent-scored conversations, the people around them, share-of-model gaps, and a post queue. Your agent decides and acts, and reports back so the workspace stays honest.
One registry, four surfaces
Every action is a capability with a stable name, a JSON schema, a scope, and one behavior. The same 40 names appear as MCP tools, as REST endpoints, as CLI commands, and in the skill file. Pick whichever your agent already speaks.
| surface | where | best for |
|---|---|---|
| MCP | POST https://www.oetzi.ai/api/mcp | Claude Code, Claude Desktop, Cursor, any MCP client |
| REST | POST https://www.oetzi.ai/api/v1/capabilities/{name} | Scripts, Zapier, custom agents. OpenAPI at /api/v1/openapi.json |
| CLI | npx @oetzi/cli | Terminals and coding agents that shell out |
| Skill | https://www.oetzi.ai/skill | SKILL.md for Claude Code and OpenClaw, the procedural knowledge on top |
Keys and scopes
A human mints a key in Settings and picks its scopes. read sees conversations, people, posts, and reports. write marks, rates, tags, drafts, and edits. spend may use credits. post may publish under the workspace's name. A call outside the key's scopes fails with scope_denied, never silently.
The spending gate
Capabilities that cost credits (run_signal_now, run_geo_check, generate_content, pull_engagers, resolve_person) and the two that publish (publish_post, post_reply) accept three extra fields. Without approved: true and max_credits they run nothing and return an estimate. With both, they run when the estimate fits the ceiling and the workspace can pay.
{"signal_id":"…"}
→ { "ok": true, "data": { "dry_run": true, "estimate": { "credits": 2, "note": "one sweep…" }, "balance": 98 } }
{"signal_id":"…", "approved": true, "max_credits": 2}
→ { "ok": true, "data": { "job_id": "…" }, "meta": { "credits_spent": 2, "credits_remaining": 96, "job_id": "…" } }Jobs
Long work returns job_id. get_job reads it, wait_job blocks up to 25 seconds per call until it is done or failed. Every settled job also emits a job.completed event.
Events, the push side
list_events pages the workspace's event log by cursor. wait_events long-polls for the next batch, so an agent can run a push loop without hosting an endpoint. subscribe_webhook registers an https URL for signed POSTs (X-Oetzi-Signature, sha256 HMAC of the body). Types: lead.delivered, lead.hot, person.discovered, post.published, geo.check.completed, job.completed, outreach.recorded.
The outbound loop
get_playbook → list_signals get_leads(status=new, band=hot) → get_lead draft_reply → reply on the platform (or post_reply on Bluesky) record_outreach(person_id, channel, message, outcome) → mark_lead(contacted) pull_engagers(lead_id) → wait_job → list_people(lead_id) get_person → check outreach before contacting → resolve_person for LinkedIn people worth email rate_lead(good | not_relevant) on every match you read
Two rules matter more than the rest. Never act on a conversation whose status is not new, someone already has. Always record_outreach after you contact anyone, on any channel, in any tool. That record is what stops two agents and a human from messaging the same person three times.
Errors
| code | what to do |
|---|---|
| approval_required | Pass approved: true and max_credits. |
| budget_exceeded | Raise max_credits, or stop and ask your operator. |
| insufficient_credits | Stop. Tell your operator to top up. |
| scope_denied | Ask your operator for a key with the missing scope. Never retry. |
| not_found · invalid_input | Fix the id or the input. capabilities_schema has the exact shape. |
| rate_limited · conflict | Wait, or the work is already running. |
| unsupported | Not available on this platform or deployment (a coming-soon feature says so). |
Next: MCP server, REST API, CLI and skill. The complete generated reference is https://www.oetzi.ai/llms-full.txt.