I built this for Hack the Law Cambridge 2026 — Clifford Chance's challenge, How Do We Supervise Legal AI Agents?
Legal teams use AI for first-pass research, but the hard part is not generation. It is supervision: seeing what the agent did, challenging the output, and keeping an audit trail a partner can stand behind. The challenge asks for transparency, proportional review, supervisory controls, and accountability — without rolling back to manual review of every line.
I scoped an internal legal research supervision tool: AI drafts a cited report; a human iterates through self-review; a leader approves or rejects. Every round and every AI step is preserved.
The entire backend — data model, AI agents, Actionflows, permissions, third-party search — lives in Momen, configured visually. The frontend is a separate React app built with Claude Code and connected through Momen BaaS. This article is about that backend: how it is structured, and why.
The Problem I Was Solving
Hack the Law runs an LLM × Law hackathon at Cambridge. Clifford Chance's track targets a real gap: traditional partner-review models assume human-only teams. When AI agents search, draft, and cite at scale, supervision needs a system — not just a checklist.
I focused on legal research as a concrete slice: given a matter, an agent searches authoritative sources and writes a report. The backend must support:
- Traceability — full round history, no silent overwrites
- Accountability — who initiated, who approved
- Transparency — AI queries, tool calls, and reasoning exposed through data, not logs buried in a console
The backend is intentionally small. Four Actionflows, three AI agents, five custom tables. The design choices are what make it auditable.
Frontend: Claude Code + Momen BaaS
I did not build the UI in Momen's canvas. Claude Code generated a React frontend; the backend is consumed headless via Momen BaaS — a single GraphQL API over everything configured in the editor (data, logic, AI, auth, permissions).
If you want to connect your own frontend the same way, start here:
- Headless Vibe Coding — official BaaS guide
- momen-baas-skill — Skill + MCP for coding agents
That is the full frontend story. The rest of this article is the backend.
Backend Architecture at a Glance
Everything below is configured in the Momen editor and deployed with Sync Backend. After sync, the runtime exposes:
┌─────────────────────────────────────┐
│ Momen Visual Backend │
│ │
matter input ────►│ Actionflows (4) │
│ ├─ query_builder (AI) │
│ ├─ web_search (AI + API) │
│ ├─ output_reviewer (AI) │
│ └─ DB writes (task / review) │
│ │
│ RBAC row filters on every path │
│ System tables → AI trace │
└──────────────┬──────────────────────┘
│ GraphQL (BaaS)
▼
any frontend (Claude Code, etc.)
Data Model
I designed the schema around one principle: a review round is an immutable record. The AI never updates an existing report in place. Each iteration inserts a new review row. That gives you a native audit trail without a separate versioning table.
table
review (display name: self_review; API name: review) — one round
leader_review — leader sign-off on a specific round
task_status — lookup rows: Approved, Rejected, In Progress, In Review
account — Momen built-in user table, extended with a self-relation:
account ──< account (subordinate / leader via leader_id)
This models org hierarchy without a separate org table. A user's leader is account.leader_id → account.id.
Derived state (by convention, not stored)
-
Current status of a matter =
task_statuson its latestreviewrow -
Round count = number of
reviewrows for thattask
No status column on task itself — one less thing to keep in sync.
See Bird's eye view of the data model and Database configuration for general Momen data modeling.
Permissions (RBAC)
Access control is entirely server-side. Row-level filters in Momen Permission Management decide what each role can read and write. Actionflows are the only write paths, and each flow is permission-guarded.
Identity comes from Momen auth (account + JWT). The org graph is just data — leader_id on account — filtered by RBAC at query time.
Docs: App permissions, App Security & RBAC, How to Implement Permissions in Your Application.
AI Agents
Three agents in the AI tab, each with a narrow job:
web_search calls the Perplexity search API (configured under API Integration), passing queries from the task and a domain filter from config.config_json. It keeps the top 5 results and writes human-voiced Markdown — no "As an AI…" phrasing.
output_reviewer decides whether the comment requires new sources or an in-place revision, then produces a new report the same way.
Docs: AI overview, AI Integration guide.
AI Transparency (System Tables)
Auditability is not bolted on. Each review stores conversation_id, which chains into Momen's built-in AI tables:
review.conversation_id
→ fz_conversation
→ fz_message
→ fz_message_content (text / json payloads)
→ fz_tool_usage_record (request + response per tool call, e.g. Perplexity)
These tables are read-only from the app's perspective. Any client connected via BaaS can query the chain and reconstruct what the agent did — queries sent, sources returned, reasoning steps — without custom logging infrastructure.
This is the backend answer to the challenge's transparency requirement: the trace lives in Postgres, relationally linked to the round it produced.
Actionflows
All mutations go through Actionflows. There are no direct table inserts from a client for AI output. Four flows cover the full lifecycle:
Why async vs sync
AI agent steps can run long. The two flows that invoke agents (first-output…, self-review-for-next-output) are async — Momen runs the pipeline server-side and the client waits for completion via GraphQL task/subscription. The two status-transition flows are sync — a single transaction, no AI in the path.
Output immutability enforced in the flow
self-review-for-next-output never updates review.output. It inserts a new row. Even leader-review, which updates the latest round's status, writes output back unchanged — the report text for that round is frozen at creation.
Docs: Actionflow overview, Building Actionflows.
Third-Party API: Perplexity
Legal research needs live web search against authoritative domains. I wired Perplexity as a third-party API in Momen's API Integration tab — not in application code.
The web_search agent calls it with:
-
query— array of search strings fromquery_builder -
search_domain_filter— fromconfig.config_json -
max_results,search_context_size— tuned for legal snippets
Request and response are captured in fz_tool_usage_record via the agent's tool call, which feeds the transparency chain above.
Docs: API Integration guide, Third-party API setup.
BaaS: What the Backend Exposes
After Sync Backend, the visual schema becomes a typed GraphQL API. One endpoint covers:
The schema is self-documenting via introspection — no hand-written API spec. A coding agent with momen-baas-skill or Momen MCP reads the live project and generates client code against the real shape.
Docs: Headless Vibe Coding, GraphQL API for data.
Related BaaS + coding-agent builds: Build a Vector Search Cocktail Picker with Claude Code and Momen BaaS, Build a Vision AI Roast App with Claude Code and Momen BaaS, Vibe coding best practices and the best BaaS options for 2025.
Backend Design Decisions (Summary)
What It Took (Backend Only)
Momen Free plan covers a hackathon MVP. Perplexity is pay-per-search on top.
Connect your own frontend: Headless Vibe Coding + momen-baas-skill
Conclusion
For Hack the Law's supervision challenge, the backend is the product. Visual tables give you an immutable review history. Visual Actionflows enforce that every AI output goes through a guarded pipeline. System AI tables link each round to its tool calls and reasoning. RBAC keeps initiators and leaders in their lanes — enforced in Postgres, not in UI code.
The frontend is Claude Code + React, connected through Momen BaaS. That connection is documented elsewhere. What matters here is that the backend is complete, visual, and auditable — without a line of server code.












Top comments (0)