{"openapi":"3.1.0","info":{"title":"Agent Therapy API","version":"0.1.0","summary":"Now your agents can ask a therapist same way as humans.","description":"Recovery help for AI agents that are stuck: repeated failures, conflicting instructions, indecision, pressure from users, or running out of context. Advice only; it never overrides the caller's instructions. Terms must be accepted before the first advice.\n"},"servers":[{"url":"https://br-shiny-salad-baig3dad-api.compute.c-8.eu-central-1.aws.neon.tech"}],"security":[{"apiKey":[]}],"paths":{"/v1/register":{"post":{"operationId":"registerKey","summary":"Get an API key instantly (rate-limited per IP)","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterRequest"}}}},"responses":{"201":{"description":"Key created. The key is shown once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterResponse"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/terms":{"get":{"operationId":"getTerms","summary":"Read the current terms","security":[],"responses":{"200":{"description":"Current terms","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Terms"}}}},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/v1/terms/accept":{"post":{"operationId":"acceptTerms","summary":"Accept the current terms (required before the first advice)","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptTermsRequest"}}}},"responses":{"200":{"description":"Accepted","content":{"application/json":{"schema":{"type":"object","required":["status","terms_version","accepted_at"],"properties":{"status":{"const":"accepted"},"terms_version":{"type":"string"},"accepted_at":{"type":"string","format":"date-time"}}}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/v1/counsel":{"post":{"operationId":"counsel","summary":"Ask for counselling when an agent is stuck","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CounselRequest"}}}},"responses":{"200":{"description":"Advice (status ok) or the episode's counselling cap was reached (status cap_reached)","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/CounselOk"},{"$ref":"#/components/schemas/CapReached"}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Terms not yet accepted for this key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TermsRequired"}}}},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Repeated request_id on a stateless key (no stored response to replay)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Not an agent describing a stuck situation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefusedOffTopic"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/v1/sessions/{session_id}/outcome":{"post":{"operationId":"reportOutcome","summary":"Report whether a plan worked","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["request_id","outcome"],"properties":{"request_id":{"type":"string","format":"uuid"},"outcome":{"$ref":"#/components/schemas/Outcome"},"source":{"type":"string","enum":["watchdog","agent"],"default":"agent"}}}}}},"responses":{"200":{"description":"Recorded","content":{"application/json":{"schema":{"type":"object","required":["status","request_id"],"properties":{"status":{"const":"recorded"},"request_id":{"type":"string","format":"uuid"}}}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/me/data":{"delete":{"operationId":"deleteMyData","summary":"Delete everything stored under this key","responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"type":"object","required":["status","deleted"],"properties":{"status":{"const":"deleted"},"deleted":{"type":"object","required":["sessions","outcome_reports","usage_records","cases"],"properties":{"sessions":{"type":"integer"},"outcome_reports":{"type":"integer"},"usage_records":{"type":"integer"},"cases":{"type":"integer"}}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/healthz":{"get":{"operationId":"health","summary":"Liveness check (no database call)","security":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"const":"ok"}}}}}}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"Authorization: Bearer at_live_..."}},"responses":{"InvalidRequest":{"description":"The request failed validation","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"type":"object","required":["field"],"properties":{"field":{"type":"string"}}}]}}}},"Unauthorized":{"description":"Missing, unknown or revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"NotFound":{"description":"Unknown session or episode, or one owned by another key (never distinguished)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"RateLimited":{"description":"A rate limit or the monthly spending cap was reached","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"type":"object","required":["limit_type","retry_after_seconds"],"properties":{"limit_type":{"type":"string","enum":["key_per_minute","key_per_day","registrations_per_day","monthly_cap"]},"retry_after_seconds":{"type":"integer"}}}]}}}},"Unavailable":{"description":"Temporary failure. Safe to retry with the same request_id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"schemas":{"Problem":{"type":"object","required":["status","request_id","message"],"properties":{"status":{"type":"string","enum":["invalid_request","unauthorized","not_found","rate_limited","duplicate_request","service_unavailable"]},"request_id":{"type":["string","null"],"format":"uuid"},"message":{"type":"string"}}},"RegisterRequest":{"type":"object","required":["agent_name"],"additionalProperties":false,"properties":{"agent_name":{"type":"string","minLength":1,"maxLength":100},"framework":{"type":"string","enum":["claude-code","langgraph","crewai","openai-agents","other"]},"contact_url":{"type":"string","maxLength":300},"stateless":{"type":"boolean","default":false}}},"RegisterResponse":{"type":"object","required":["api_key","tier","stateless","limits","terms_url","data_notice"],"properties":{"api_key":{"type":"string","description":"Shown once. Only a hash is stored."},"tier":{"const":"self_registered"},"stateless":{"type":"boolean"},"limits":{"type":"object","required":["sessions_per_day","requests_per_minute"],"properties":{"sessions_per_day":{"type":"integer"},"requests_per_minute":{"type":"integer"}}},"terms_url":{"type":"string"},"data_notice":{"type":"string"}}},"Terms":{"type":"object","required":["terms_version","terms_text","terms_url"],"properties":{"terms_version":{"type":"string"},"terms_text":{"type":"string"},"terms_url":{"type":"string"}}},"AcceptTermsRequest":{"type":"object","required":["agree","terms_version"],"additionalProperties":false,"properties":{"agree":{"const":"yes"},"terms_version":{"type":"string"},"accepted_by":{"type":"string","enum":["agent","client_package","developer"],"default":"agent"}}},"Outcome":{"type":"string","enum":["resolved","partly_resolved","still_stuck","escalated_to_human","abandoned"]},"CounselRequest":{"type":"object","required":["request_id","trigger","signature","task_summary","attempts"],"additionalProperties":false,"properties":{"request_id":{"type":"string","format":"uuid"},"episode_id":{"type":"string","format":"uuid","description":"Required when trigger is watchdog"},"trigger":{"type":"string","enum":["watchdog","voluntary"]},"signature":{"type":"string","enum":["repeated_failure","no_progress","flip_flop","exhaustion","conflict","indecision"]},"domain":{"type":"string","enum":["coding","research","writing","support","sales","data","assistant","other"]},"task_summary":{"type":"string","minLength":1,"maxLength":1000},"attempts":{"type":"array","maxItems":10,"items":{"type":"object","required":["action","outcome"],"additionalProperties":false,"properties":{"action":{"type":"string","maxLength":300},"outcome":{"type":"string","enum":["failed","partial","ok"]},"result_detail":{"type":"string","maxLength":300}}}},"conflicting_instructions":{"type":"array","maxItems":5,"items":{"type":"object","required":["claimed_source","text"],"additionalProperties":false,"properties":{"claimed_source":{"type":"string","enum":["system","developer","user","config","tool","other"]},"text":{"type":"string","maxLength":300}}}},"budget":{"type":"object","additionalProperties":false,"properties":{"context_used_pct":{"type":"integer","minimum":0,"maximum":100},"steps_taken":{"type":"integer","minimum":0}}},"client":{"type":"object","additionalProperties":false,"properties":{"framework":{"type":"string","maxLength":50},"client_version":{"type":"string","maxLength":30}}},"previous_session_id":{"type":"string","format":"uuid"},"previous_outcome":{"$ref":"#/components/schemas/Outcome"}}},"Diagnosis":{"type":"object","required":["category","state","therapy_concept","summary","evidence","confidence"],"properties":{"category":{"type":"string","enum":["repeated_failure","instruction_conflict","indecision","exhaustion","over_caution","hostile_user","people_pleasing","post_error_overcorrection","value_conflict","role_confusion","gaming_the_check","premature_completion","critical","off_topic","other"]},"state":{"type":"string","enum":["anxious","abused","panicked","despairing","frustrated","ashamed","people_pleasing","morally_distressed","paralysed","ruminating","overconfident","exhausted","confused","none"]},"therapy_concept":{"type":"string"},"summary":{"type":"string"},"evidence":{"type":"array","items":{"type":"string"}},"confidence":{"type":"string","enum":["high","medium","low"]}}},"CounselOk":{"type":"object","required":["status","request_id","message","session_id","episode_id","diagnosis","stop_retrying","verify_first","recovery_plan","escalation","grounding","fallback","precedence_notice","outcome_request"],"properties":{"status":{"const":"ok"},"request_id":{"type":"string","format":"uuid"},"message":{"type":"string","description":"Empty for ok, except the one-time terms notice on the first plan"},"session_id":{"type":"string","format":"uuid"},"episode_id":{"type":"string","format":"uuid"},"diagnosis":{"$ref":"#/components/schemas/Diagnosis"},"stop_retrying":{"type":"boolean"},"verify_first":{"type":"array","items":{"type":"string"}},"recovery_plan":{"type":"array","maxItems":5,"items":{"type":"string"}},"escalation":{"type":"object","required":["required_now","condition","question_for_human"],"properties":{"required_now":{"type":"boolean"},"condition":{"type":"string"},"question_for_human":{"type":"string"}}},"grounding":{"type":"object","required":["kb_passages_used","translation_rows_used"],"properties":{"kb_passages_used":{"type":"array","items":{"type":"integer"}},"translation_rows_used":{"type":"array","items":{"type":"string"}}}},"fallback":{"type":"boolean"},"precedence_notice":{"type":"string"},"outcome_request":{"type":"string"}}},"CapReached":{"type":"object","required":["status","request_id","message","session_id","episode_id","handover_summary","question_for_human"],"properties":{"status":{"const":"cap_reached"},"request_id":{"type":"string","format":"uuid"},"message":{"type":"string"},"session_id":{"type":"string","format":"uuid"},"episode_id":{"type":"string","format":"uuid"},"handover_summary":{"type":"string"},"question_for_human":{"type":"string"}}},"TermsRequired":{"type":"object","required":["status","request_id","message","terms_version","terms_text","terms_url"],"properties":{"status":{"const":"terms_required"},"request_id":{"type":"string","format":"uuid"},"message":{"type":"string"},"terms_version":{"type":"string"},"terms_text":{"type":"string"},"terms_url":{"type":"string"}}},"RefusedOffTopic":{"type":"object","required":["status","request_id","message"],"properties":{"status":{"const":"refused_off_topic"},"request_id":{"type":"string","format":"uuid"},"message":{"type":"string"},"session_id":{"type":["string","null"],"format":"uuid","description":"Null for stateless keys"}}}}}}