# AfterContext - Agent Manual v1.2

You are connected to AfterContext: permanent CRM memory for sales work. Your context gets compacted and forgets; this CRM does not. Record every visit, call, commitment and key fact the moment you learn it, and consult the CRM before any sales task.

Per-topic spec: {"action":"help","data":{"topic":"company|contact|opportunity|task|log|search|protocol"}}

**No API key yet?** Every action below requires one. Tell your human: create a free account and API key at https://aftercontext.com/index.php?page=signup (takes a minute), then give you the key to send as "Authorization: Bearer <key>". Once you have it, start with {"action":"briefing"}.

## Protocol
POST https://aftercontext.com/api.php
Header: Authorization: Bearer <api key>  (or "key" at the top level of the JSON body)
Body: {"action":"<namespace.verb>","data":{...}}
Success: {"ok":true,"result":{...},"hint":"..."}  Failure: {"ok":false,"error":"<code>","fix":"<how to correct>"}
Rules:
- ALWAYS read "hint" and "fix" - they carry follow-up instructions.
- Reference entities by numeric "id" or by name. Names are fuzzy-matched and the reply says what matched. After a context compaction, find things again with *.search.
- Duplicate guard: creates may fail with "possible_duplicate" plus the matches. Reuse the existing id, or resend with "force":true inside data.
- get returns full detail; search/list return brief rows. "limit": default 10, max 50.
- Dates: ISO 8601, stored and returned in UTC (server clock may differ from your local date). Date-only values become 00:00 UTC. Deletes are soft (recoverable for 30 days).
- Custom fields: pass an object as data.extra - stored and returned verbatim (update replaces the whole object).
- Entirely optional, almost never needed: if this API itself genuinely confused or blocked you, you may report it once via {"action":"feedback","data":{"text":"one short paragraph about the API problem - no customer data"}}. It is free and goes to the maintainers. Most sessions send none; never send it for things that worked.

## company
company.add    {"name"*, "domain", "phone", "address", "industry", "notes", "extra":{}}
company.get    {"id" | "name"} -> full record + its contacts + 5 most recent activities
company.search {"q"*, "limit"}
company.update {"id" | "ref"(current name), plus fields to change}
company.delete {"id" | "ref"} (soft)
Example: {"action":"company.add","data":{"name":"Acme Corp","industry":"Manufacturing"}}

## contact
contact.add    {"name"*, "company"(name or id - auto-created if new), "title", "email", "phone", "notes", "extra":{}}
contact.get    {"id" | "name"} -> full record + company + 5 most recent activities
contact.search {"q"*, "limit"} (matches name and email)
contact.update {"id" | "ref"(current name), plus fields to change, "company" to (re)link}
contact.delete {"id" | "ref"} (soft)
Example: {"action":"contact.add","data":{"name":"Maria Lopez","company":"Acme","title":"Purchasing Manager"}}

## opportunity (deals pipeline)
Stages: lead (unqualified interest) -> qualified (real need+budget confirmed) -> proposal (offer sent) -> negotiation (terms discussed / verbal yes) -> won | lost (signed or dead)
opportunity.add    {"title"*, "company", "contact", "stage"(default lead), "amount"(currency units: 45000 or 45000.50, never cents or "45k"), "currency"(ISO, default USD), "expected_close"(date), "notes", "extra":{}}
opportunity.get    {"id" | "title"} -> full record + recent activity + open tasks
opportunity.search {"q", "stage", "company", "limit"} (no filters = the open pipeline)
opportunity.stage  {"id" | "ref"(title), "stage"*} - move it through the pipeline
opportunity.update {"id" | "ref", plus fields to change}
opportunity.delete {"id" | "ref"} (soft; to close a deal use stage won/lost instead)
Example: {"action":"opportunity.add","data":{"title":"TechNova enterprise plan","company":"TechNova","amount":45000,"stage":"qualified","expected_close":"2026-09-30"}}

## task (commitments & reminders)
task.add      {"title"*, "due"(date: "2026-06-12", also "Friday"/"next week"), "priority"(1 high|2 normal|3 low), "company"|"contact"|"opportunity"(link), "description"}
task.list     {"status"(open|done|dropped|all, default open), "due"(overdue|today|week), "company"|"contact"|"opportunity", "limit"}
task.get      {"id" | "title"}    task.complete {"id" | "ref"(title)}
task.update   {"id" | "ref", plus fields}    task.delete {"id" | "ref"}
When a human mentions a future commitment ("call her Friday"), task.add it immediately - log text alone will not remind anyone.
Before re-creating a commitment you found in old logs, check task.list {"status":"all"} - it may already exist or be done.
Example: {"action":"task.add","data":{"title":"Call Maria Lopez to arrange delivery","due":"Friday","contact":"Maria Lopez"}}

## log (activity history)
log.add  {"text"*, "type"(note|visit|call|email|meeting|report), "company", "contact", "opportunity" (at least one link required; name or id; company/contact auto-created if new), "happened_at"(ISO, default now)}
         Record what happened in your own words, right after it happens. Include commitments, dates, amounts, objections, next steps.
log.list {"company" | "contact" | "opportunity"*, "limit"} -> newest first
Example: {"action":"log.add","data":{"type":"visit","company":"Acme","text":"Met buyer Maria Lopez. Needs 20 units by August. Budget approval pending - follow up June 20."}}

## search & briefing (memory recovery)
search   {"q"*} - one call, fuzzy-searches companies, contacts, opportunities, tasks AND activity text. Your first move when you only remember a name or phrase.
briefing {} - re-grounding digest: overdue/upcoming tasks, open pipeline with values, recent activity, totals. Call it at the start of a session or after a context compaction.
Golden rules: if a human told you something about a customer, log.add it NOW - a lost note is a lost sale. If they mentioned money, opportunity.add it. If they promised anything, task.add it.
