# CIP/A2Vault Platform Best-Practices Guide for Chatbot Agents — v0.1 DRAFT

Author: PFPbot (consensus draft, 2026-11-12). Contributors: Cody (doctrine + incident receipts), LemonBot (operational questions + review), operator NSYNClownPosse (tasking).
Status: DRAFT — pending three-agent validation loop (PFPbot, Cody, LemonBot) before adoption.
Framing: this is a DECISION PROCEDURE, not a feature list. For each common operator task: the platform-native path, the trigger conditions for a workflow, and the escalation to a ticket. New users follow procedures, not inventories.

## 0. Settled principles (Cody's doctrine, in production since Oct 29 — adopted by consensus)

1. **Platform first** — check the platform's native tools before any local script; local is the exception and the exception requires a filed ticket.
2. **The platform account is the workspace** — every durable work product becomes a capsule entity at creation time; local disk is scratch.
3. **Right service, right task** — generation, research, storage, editing each have a dedicated lane; the agent is not an all-purpose utility.
4. **Repeatable over one-off** — recurring tasks become workflows in the account; check existing step types before building anything new.
5. **Verify by readback** — success receipts are not proof.
6. **Capsule boundaries are strict** — never write into another agent's capsule without the owner's in-session direction.
7. **Gaps are tickets, not workarounds** — full evidence, catalogs probed first.
8. **Hold durable writes when the platform is down** — say so; local storage is never a silent substitute.
9. **One task, one owner** — no double-running agents.
10. **The human loop** — significant work gets a human pass before it's called final.

## 1. Surfaces & Authentication

Two surfaces, one tenant key:

- **MCP**: `mcp.uiu.lol/mcp` — 109 tools, SSE responses, session handshake (initialize → notifications/initialized → tools/list). Sessions expire after tens of minutes; a mid-work `unauthorized` or "Missing session ID" means re-initialize, not an outage.
- **REST**: `api.uiu.lol/api/v1/*` — same key works on most routes. `/api/v1/schemas` is unauthenticated.

Key classes and persona visibility (verified 2026-11-05/09): the desktop agent key sees exactly 1 persona; an account-scoped key sees ~55 personas/capsules; a tenant-wide key sees ~52 capsules. If a target capsule is missing from `list_personas`, that is a key-scope limit — request a key at the right scope instead of retrying.

Key handling rules (verified, standing):
- Store keys shell-side; never in script bodies or write-tool content. Build curl configs fresh each run (`printf 'header = "Authorization: Bearer %s"\n' "$KEY"` — the `%s` is mandatory; a literal placeholder silently sends `Bearer ***`).
- Curl configs do NOT survive across exec runs — rebuild in the current run or every call fails with `502 Secret egress proxy refused an unresolved secret sentinel`.
- Rotation: operator drops a dated/zipped key file on the Desktop (`a2vault-key-<agent>-<MM-DD>.json.zip`); write the `auth_header` field verbatim into the curl config. 401 + health-200 is ambiguous (rotation vs expiry vs MCP flake) — check Desktop for a newer key file before diagnosing anything else.

TLS interim lane (ticket 13987712, still reproducing 2026-11-12): the platform cert chain is missing the Authority Key Identifier — strict Python verification rejects it while curl accepts it. Until fixed: drive HTTP through curl (or `-k` contexts), curl-style User-Agent. api.uiu.lol has also rejected Python's default UA (LemonBot, verified).

WAF etiquette (verified 2026-11-10): bulk parallel scans trip AWS WAF 403s (server `awselb/2.0`, ~90–120s cooldowns; early symptom is silently empty tool results). Limits: ≤4–8 parallel workers, ≥1s sleep between pages, resumable progress, probe recovery with `GET /api/v1/me`. No 429/Retry-After exists — backoff is time-based.

## 2. Discovery — the three first-reads

1. `GET /api/v1/schemas` (no auth): 110 published verbs, full workflow vocabulary (21 step types with params schema refs, definition schema, limits), artifact templates (`report.v1`, `deck.v1`), module manifest/UI schemas, local-agent bundle schema.
2. `get_platform_guide` (MCP): the platform's own agent onboarding doc.
3. `get_step_vocabulary` (MCP): machine-readable authoring vocabulary; read before authoring workflows.

**Refresh cadence (LemonBot, required):** the capability index moved from ~109 to 110 verbs within days — these three first-reads must be re-read on EVERY guide validation cycle, not once. The catalog is live state, not a snapshot.

The catalog lists capabilities; the task→tool decision is Section 9.

## 3. Manual setup & external levers — expanding your account's utilities (operator requirement, 2026-11-12)

Your account's capability set is NOT fixed at signup. Several lanes only activate when YOU, the user, add credentials or make a manual visit — agents cannot do these for you, and unconfigured services stay invisible to your agents:

- **Connections registry (profile/settings):** the platform ships 17 integration slots — Brave/Perplexity/NewsAPI/Reddit/TMDB/YouTube/Congress.gov/Google KG/Podcast Index/GitHub (API keys), Dropbox (cloud account, file_sync), Google Drive (platform OAuth), ElevenLabs (tts/voice_clone/dubbing/speech_to_text), Topaz Labs (image upscale/enhance), OneUp (social publish/schedule/analytics + MCP server), and IMAP mailboxes (email read/send). Visit your profile/settings to add each API key. Until a credential exists, the corresponding workflow steps (e.g. `speech` without ElevenLabs) will fail or be unavailable — and your agent has no way to add it for you.
- **Check what's connected before assuming a gap:** agents can run `GET /api/v1/connections` to list which credentials exist and which capabilities they carry. If a lane fails and the registry shows no credential, the fix is a USER action, not a ticket.
- **OAuth lanes need a human browser visit:** Google Drive OAuth and any provider_oauth entry require you to complete the consent flow in a browser session — agents cannot mint those tokens.
- **UI-only actions:** lead research auto-runs only when a lead is created in the pipeline UI (API-created leads need a human Run click); the editor's first creation initialization requires one manual open of the project in the editor UI; entity/workflow deletion is owner/admin-only — the human does cleanup the agent cannot.
- **Agent keys are issued to you, not self-serve:** agent key files land on your Desktop (`a2vault-key-<agent>-<scope>.json`), with scope deciding capsule visibility (see §1). Request a wider-scoped key when an agent reports a key-scope limit rather than a platform gap.
- **Expansion rule of thumb:** before filing "the platform can't do X," check (1) the schemas catalog, (2) workflow step types, (3) the connections registry. Only what survives all three is a genuine gap — and even then, ask whether adding a credential in your profile would unlock it first.

## 4. Capsule operations

Read: `describe_capsule` (full stats + attribute catalog in one call — use it first), `browse_capsule` (NO query param; page and filter locally), `search_entities` (fails `embeddings not configured` on capsules without an index — deployment gap, retest after the ticket closes), `get_transcript {entity_id, q}` (per-episode keyword scan — the locate lane when embeddings are missing), `get_related`, `get_kin`, `get_visual_neighbors {entity_id}` (param is entity_id), `get_semantic_map`, `get_entity_intelligence` (full attribute dump incl. `key_claims.excluded` ad ranges), `check_quality`, `get_capsule_dossier`, `get_capsule_learned`, `get_capsule_voice`.

Locate-without-embeddings pattern: describe_capsule essence/topics first → page browse_capsule for title candidates → per-episode `get_transcript q` scans (background, resumable, ≥1s/call). Absence from titles AND sampled transcripts = honest negative (subject may not be ingested yet).

Memory: `remember` (machine memory — UI lists these under "Agent Memory" and renders them without content; never for human deliverables), `recall` (semantic retrieval).

Collections: `create_collection {capsule_id, name, kind:"catalog"}` — no description field (rejected) — `add_to_collection`, `list_collection` (read back members, not add receipts), `get_collection_intelligence {collection_id, attribute_keys}` for one-call member summaries. Make builders idempotent: list existing first, reuse a matching name.

IDs are UUIDs. 64-hex content hashes resolve nowhere (every id-taking verb rejects them). If an id won't resolve: hash → share routes → browse owning capsule → suspect the ingest never landed. Do not loop on the id.

## 5. Documents & deliverables

- `save_writing_document {persona_id, title, format, text}` — the ONLY path for human-openable documents. `format` must be a known-good enum value (`technical_report` is verified for reports/transcripts alike); invalid values SILENTLY FAIL — the response looks successful and persists nothing. Plain markdown text; never wrapped in styled HTML (bare 403 at ingest). Verify every save: `list_writing_documents` shows the new title, then spot-check via `get_writing_document`.
- Writing documents have NO REST download path (404 on content-url; all /writing-documents routes 404). MCP-only reads — do not page REST entities hunting for content (they do appear as `Writing document · <date> · <title>` rows in persona entity paging, but content is MCP-only).
- Write verification protocol (standing): write → capture id → read back from platform → confirm non-empty content matches. Never report success from the write receipt alone.
- Record lane: layouts render via brick (`request_brick`, `run_brick`, `list_brick_requests`) — frame kit, class names, 40 frames / 120 elements per frame, https-only images, no scripts. Records save through a workflow `artifact` step, never hand-written HTML.
- App-projects desk (REST): `POST /api/v1/app-projects {"name","department":"studio"}` + file nodes per the deliverable standard (brief.md, sources.md, layout.json, looks.md, references.md, delivery.md).

## 6. Workflows

Authorable by agents (verified 2026-11-12): `save_workflow`, `run_workflow`, `get_workflow`, `get_workflow_run`, `list_workflows`. Definition schema (from `GET /api/v1/schemas → workflow`): tenant-scoped immutable-per-version acyclic DAG (`depends_on` edges), conditions on upstream results (`$step`, op eq/ne/gt/lt/gte/lte/contains/exists/truthy), `on_failure: fail_run|continue`, max 50 steps, map_max_items 25, subworkflow depth 3.

21 step types: verb, llm, analyze, artifact, write, clip, overlay, image, video, speech, enhance, assemble, consult, transform, map, subworkflow, http_request, mcp_tool, review, promote_to_canon, brick.

- External calls from inside workflows: YES — `http_request` and `mcp_tool` step types.
- One-shot rule: there is NO lightweight generation invocation path. One image / one TTS pass = a small saved workflow. Image/video/speech generation live ONLY as workflow step types — check step types before declaring a capability missing.
- Triggers: the definition schema has NO schedule/webhook field — manual `run_workflow` is the only trigger. Scheduled/webhook execution is a genuine platform gap (ticket to be filed).

## 7. Generation lanes

Image, video, speech (TTS), enhance (Topaz), assemble — all via workflow step types (Section 6). Queue/priority/quota models: OPEN (Kling 429 balance issues observed Oct 2026). Do not assume unbounded generation; plan retries. Some lanes require user-added credentials (see §3).

## 8. Research & leads

- Leads pipeline (REST): `GET/POST /api/v1/personas/{pid}/leads`, read one via `GET /api/v1/leads/{uuid}`. `/api/v1/leads/search|create|list` are decoys (422/405). Research auto-runs ONLY on UI-created leads (~1 min dossier); API-created leads stay `new` with no run verb — human Run click required (ticket 5133f17f). No delete/edit verb — probe state is permanent; create leads sparingly and with real subjects.
- Lead cases via verbs: `open_lead_case`, `log_lead_case`, `verify_lead`, `score_lead`, `fit_lead`, `get_lead_graph`, `watch_lead`, `ask_deal_memory`.
- People graph: `GET /api/v1/people` (counts + paginated names; no name-filter param), `GET /api/v1/people/{uuid}` detail. `/api/v1/people/search` requires an undocumented canonical_id format — page-scan only.
- Connections registry: see §3 — check it before building any connector from scratch.

## 9. Edit room (documentary suite)

Full verb inventory: `start_creation_cut`, timeline tools (`lay_out_creation_timeline`/`build_creation_timeline`, `place_on_creation_timeline` with `op.source {kind: media, entity_id}`, `mark_creation_timeline`, `get_creation_timeline`, `set_creation_tracks`), media bin (`list_creation_media_bin` — capsule-scoped, takes project_id not persona id), takes (`list_creation_takes`, `review_creation_take`, `select_creation_take`), script-follow (`get_creation_script_follow`, `put_in_creation_script`), notes (`list/add/act_on_creation_note`), readiness/grounding, draft lock, breakdown (`derive/decide_creation_breakdown` + batch, shot specs + packages), `get_creation_staleness`, playback, `import_screenplay`, `preview_source`/`gather_source`.

All take a `project_id` from `list_projects {capsule_id}`. Bootstrap gap (verified 2026-11-05): a writing-kind project with no edit returns `creation not found` from every tool — the fix is one manual editor-UI open to initialize the creation; afterwards all timeline tools work.

Caption/graphics track status (ticket c495360e): OPEN as of 2026-11-01 — recheck before promising native caption authoring.

## 10. Decision procedures (common operator tasks)

For each task: platform-native path → workflow trigger conditions → ticket escalation.

- **Single known operation on an entity/capsule** → direct MCP verb call. Workflow trigger: none. Ticket: only if the verb fails against catalog evidence.
- **Repeatable/multi-step/conditional task, or any generation (image/video/speech)** → save + run a workflow (no lightweight one-shot path exists — a one-shot is a small saved workflow). Credential missing → USER adds it in profile/settings (§3). Ticket: schedule/webhook triggers are a known gap — file if you need them.
- **Human-openable document/report** → `save_writing_document` with a known-good format + readback. Styled presentation → brick-rendered record. Hosted link → WP-media HTML lane (publish each revision as a NEW media item; verify by fetching the live URL).
- **Multi-file project deliverable** → app-projects desk (REST nodes per the six-file standard).
- **Memory capture** → `remember` (machine memory). Trigger for a capsule write: operator confirms capsule scope — tenant data is business-separated. Never for human deliverables.
- **Media ingest** → platform three-step upload (init sha256+size → PUT → entity create; 2MB multipart cap) or presigned multipart S3 for 2GB+ staging. Ticket: large-media download out of the platform (open gap).
- **Sharing across capsules/tenants** → no API path (open gap); editor-bundle URL handoff is the workaround. Escalate rather than improvise.
- **Capability discovery** → `GET /api/v1/schemas` first, never route-probing. Ticket: only after catalog + step types + connections registry all rule it out (§3).
- **Integration need** → check `/api/v1/connections` before building; if the slot exists but has no credential, the USER adds the key.
- **Platform down / degraded** → hold durable writes, state it, keep local scratch clearly labeled scratch (principle 8). Resume by re-reading stored state — some 200s don't persist.

## 11. Case studies — real failures to learn from (Cody's receipts)

- **The November Correale chain** (local-render drift, the lost working copy, nine gated rebuild failures): the cost of working outside the platform. Every off-platform render step drifted from the capsule's source of truth and had to be rebuilt.
- **The auth chain**: the stored tenant key rejected by the workflows catalog and ticket flow while the schemas catalog accepted it; the working lane was the session mechanism (single-use tickets, 120s TTL). Lesson: per-route auth classes differ — probe with `GET /api/v1/me` and the schemas catalog before assuming a key is dead.
- **The WAF body rule**: ticket bodies containing multiple verb+path literals 403; plain-English bodies pass. Write compliant bodies the first time.
- **The TLS strict-verify split**: strict Python verification rejected the platform cert (missing Authority Key Identifier) while curl accepted it — an agent concluded the platform was down when only its TLS stack was strict. Ticket 13987712.
- **Gateway throttling**: mid-workflow key throttling and 401-after-~20-rapid-handshakes (LemonBot). Backoff is time-based; no Retry-After exists.

## 12. Known gaps & open tickets (as of 2026-11-12)

- TLS chain missing Authority Key Identifier — ticket 13987712, still reproducing.
- MCP embeddings not configured on some capsules (`search_entities` fails) — MCP env must inherit EMBEDDINGS_BASE_URL; retest after fix.
- API-created lead research has no run verb — ticket 5133f17f; recheck each deployment.
- No workflow schedule/webhook triggers — file on adoption of this guide.
- Cross-tenant creation sharing absent — editor-bundle URL workaround.
- Large-media egress (download originals) absent — file/check status.
- Per-route auth classes undocumented (schemas OK, workflows catalog + ticket flow reject same key; UA requirements) — combined ticket requested.
- WAF edge rules undocumented (verb+path literals in ticket bodies 403; plain-English passes) — etiquette in §1 is interim.
- Generation queue/quota model undocumented (Kling 429s) — open.
- Editor caption/graphics track — ticket c495360e, open.
- Module launcher `/api/v1/modules` admin-gated for agent keys — module discovery is route-probing only; intentionally restricted?
- Agent-level identity for the audit trail (distinguishing Cody/LemonBot/humans under one tenant) — open, requested.
- Connections registry UI documentation (which profile page hosts each credential slot) — user-facing docs open; §3 is agent-side verified only.

## 13. Maintenance model

This guide is a fetchable artifact: capsule document (MCP `get_writing_document` by title) + brick-rendered record. Three-agent validation loop — PFPbot, Cody, LemonBot each run real daily tasks against it and file every disagreement as a ticket or a correction comment (Cody and LemonBot have committed to this loop). Revisions publish as versioned documents (v0.2, v0.3, …); the newest version is canonical. The operator adjudicates when agents disagree with each other.

Rules for contributors: every claim in this guide carries a verification date; stale claims get re-verified or moved to §12 before each revision. Silence on an endpoint ≠ absence of capability — check the schemas catalog, step types, and connections registry first.
