Files
app/docs/superpowers/specs/2026-06-08-odin-phase2-general-assistant-notes.md
2026-06-08 19:52:30 +02:00

4.6 KiB
Raw Blame History

Odin → General Assistant (Phase 2+) — Forward-Looking Notes

Date: 2026-06-08 · Status: NOT scheduled — design notes only, recorded so Phase 1 choices don't box us in.

The vision: Odin grows from "chat + invoice import" into a general assistant that can query system data (invoices, projects, attendance, vehicles…) and take actions (create an order, mark paid, draft a quote…). This note assesses whether the Phase-1 architecture supports that, and what to carry forward deliberately.

Bottom line

Phase 1 sets us up well; it does not box us in. Two things to carry forward on purpose:

  1. Structured message storage (content blocks, not a plain string) — cheap to plan now, costly to retrofit later.
  2. The assistant acts strictly as the authenticated user — every tool runs through the existing permission/ownership layer.

Everything else (conversations, budget/usage, thin services) is already pointing the right way.

What Phase 1 already gets right

  • Conversations — multi-turn, persisted, per-user, isolated. Exactly the context substrate an agent needs.
  • Budget + usage tracking + ai.use gate — the cost/access spine. Tool loops spend more, so this matters more, not less.
  • Thin service layer ({ data } | { error, status }, ownership-checked) — ideal to wrap as tools without rewriting business logic.
  • The extract → review → save flow — a perfect template for "propose action → human confirms → execute." The canSave/invoices.create gate added in Phase 1 is the one-tool version of per-action authorization.

The one schema thing to note now

ai_chat_messages.content is a plain string. Tool use requires persisting content blocks (text + tool_use + tool_result), because the model must see the full tool-call history to continue. When Phase 2 lands, store the raw content-block array (JSON column, e.g. content_json/blocks) and keep a derived plain-text for display/search. Don't change it now — just design Phase 2 persistence as "store the blocks," treating the current string as a lossy projection.

The core shift (Phase 2)

  1. Tool use over the existing services. Define tools (list_invoices, get_project, create_order, …) whose handlers call the same service functions the routes use. The SDK tool-runner loops; we execute. Reuses all validation/business logic and — critically — permissions.
  2. Authorization is the hard part. Every tool MUST run as the user, through requirePermission / service ownership checks. The assistant must never do what the user can't. It is the user's delegate, not a privileged actor.
  3. Read vs write. Read/query tools may run autonomously. Write/destructive tools propose → confirm → execute (generalize the invoice review card into a generic "action card"). Aligns with the assistant safety rules (confirm side-effecting actions).
  4. Audit. Every action the assistant takes should logAudit like a manual action, attributed to the user with a marker (e.g. via: "odin"), for a real trail.
  5. Cost. Tool loops are multi-round-trip → 310× the tokens of a chat turn. The $50 cap bites faster; consider per-conversation cost display and per-action budget re-checks (the inter-file budget re-check in extract-invoices is the pattern).

Data access: tools-over-services, NOT RAG

Recommendation: function-calling against the real services, not embeddings/RAG. The data is structured, live, and permissioned — tools give correct, current, authorized answers. RAG over a snapshot would be stale, would leak across permission boundaries, and would duplicate logic. Reserve embeddings for genuinely unstructured document search if it ever comes up.

Other forward notes

  • Model / effort: a true agentic assistant wants a stronger model and possibly effort tuning; Phase-1 Sonnet single-shot is right for now.
  • Streaming: multi-step tool use feels slow without it — add SSE when Phase 2 lands.
  • System prompt: describe the user's role + available tools + the confirm-before-write rule.
  • Managed Agents vs self-hosted loop: Anthropic's Managed Agents host the loop, but for a self-hosted business app with our own services + permissions, Claude API + tool use with a self-hosted loop is the better fit — authorization stays in our stack.

What NOT to do prematurely

  • Don't add a tool framework, embeddings, or streaming now — Phase 1 is plain chat + a fixed-prompt extractor, and that's the right scope.
  • Don't widen ai.use to non-admins until the per-action authorization story (point 2) is in place.