Skip to content

Repository files navigation

Donald

A supervision surface for agents that act.

NextWave Hackathon 2026 · CDMX · Challenge 3 — The Interface That Builds Itself

Donald — Nauta runtime supervision


See it live

usedonald.com — no install, no signup, nothing to run.

Five runs, five different shapes, one protocol:

Run What it shows
Berríos OP-4471 the full case — an ambient watch hands off to a triggered chain when the carrier reroutes a vessel, and a human gates the action
Berríos OP-4471 · v2 the same case with the operational-stage renders
Missing invoice a cross-domain investigation: supplier invoice vs. purchase order, an exact $840 gap, our error
Replan new evidence arrives mid-flight and the graph rewires itself
Land pickup a scheduling conflict resolved without interrupting anyone

These five play from event recordings bundled into the app (frontend/lib/donald/events.*.jsonl), replayed through the exact same reducer and components as the live path. That is deliberate: the demo has no backend to be down, no database to migrate and no bill to pay, so the link works forever.

The live half — an agent reporting over MCP into MySQL, and an operator stopping it mid-run — is real code in this repo, but it is not currently hosted. Run it yourself with Self-hosting the live stack.


The problem

Companies like Nauta sell AI agents that do more than alert: they execute. They send emails, book trucks and dispute invoices, 24/7. Their own website says it plainly:

“Agents that do not send an alert and wait. They act.

That leaves a gap:

An agent that only alerts The person reads, decides and acts. The person remains in control.
An agent that acts Things happen without them. How do I trust something that has already acted?

An agent that only alerts can be audited by reading the alert. An agent that acts needs a window — and a brake.

Donald is that window and that brake. The operator watches the agent's reasoning build itself on screen as it happens, and can stop or redirect it.

We change nothing about the provider. Its stages, logic and actions stay intact. We only ask the agent to expose its intent and report when that intent changes.


How it works — the five-verb protocol

Any agent that speaks these five verbs becomes supervisable:

Verb The agent says Donald draws
DECLARE “I propose these N steps” staggered gray nodes
ADVANCE “I am on step 3; this is what I found” the node pulses and the edge draws itself
REPLAN “The plan changed: remove this, add that” the graph rewires itself
ASK “I need you to decide” the node expands into a decision panel
FINISH “I am done; this is what happened” the run collapses into a summary

What we ask for is a proposal, not a commitment:

“We know you have a lot to do. Just propose your plan — even if it changes.”

A changing plan is not failure; it means the agent learned something. If the plan never changed, the interface would never rebuild itself and there would be nothing to demonstrate. That is why every replan carries its cause (reason, triggered_by, evidence) — without it, the change looks like a mistake; with it, the system looks like it learned.


The pieces

  ANY REAL AGENT             skill/              ← teaches the agent the domain and reporting loop
  (any MCP client)              │
                               │  MCP · 5 verbs · <mcp-host>/v1/mcp
                               ▼
  backend/donald/             ← Go generated by nuzur + MCP server
            │                    entities: agent_run · agent_node · agent_edge
            │                    agent_event · intervention · artifact
            ▼
  <api-host>/v1/               ← REST + live event stream
            │
            ▼
  frontend/                   ← Next + React Flow. Snapshot + SSE deltas; the graph
                                 shape is computed from the edges, never hand-authored.
Folder What it is
backend/donald/ Go backend generated by nuzur from the v2-run-graph-events model, plus the MCP server in app/mcp/. Generated files are not edited — see backend/donald/AI.md. Custom work belongs in app/.
frontend/ Next 16 + React Flow. Graph positions are calculated from data, never hand-authored.
skill/ donald-flow teaches any agent to report through MCP; nauta-operations gives the demo agent a coherent importer data landscape.
deploy/ Helm charts for the deployed API, MCP endpoint and web surface.

Deployment and data flow

The live topology is one host running microk8s. The same container image runs twice — DONALD_ROLE=mcp serves agents, DONALD_ROLE=api serves browsers — so a slow agent cannot degrade the graph someone is watching. Green is the agent writing, blue is reading and serving, red is the operator pushing back.

Donald deployment and data flow

The red path is the whole product: an operator's stop or steer is written as an event, picked up by the agent on its next check_instructions, and honoured by changing the plan. It is advisory — these agents are not ours to kill — and the interface says so rather than pretending otherwise.

The domain model

Nine entities. agent_event is the source of truth — append-only, with a per-run monotonic sequence and a unique idempotency_key. Everything else is a materialised snapshot of it: agent_node and agent_edge exist so a client can start without replaying the whole log, and can be rebuilt from it at any time. agent_event_payload and intervention_interaction are dependent entities — typed JSON, not bare columns.

Donald domain model


Run it yourself

Node 20+ is the only prerequisite. There is nothing else to install and no service to sign up for.

git clone https://github.com/RodMed0709/nextwave-hackathon.git
cd nextwave-hackathon/frontend
npx pnpm@10 install
npx pnpm@10 dev                    # http://localhost:3000

On Windows PowerShell use npx.cmd instead of npx.

Open http://localhost:3000 and the five recorded runs replay locally — no environment variables, no API keys, no backend. That is the whole tutorial.

Two optional keys unlock two optional things:

Variable What it turns on Without it
OPENAI_API_KEY typed and spoken operator instructions get interpreted; prompt suggestions appear the buttons are there; instructions are recorded verbatim
NEXT_PUBLIC_DONALD_API any run key that is not one of the five recorded ones streams live from your own backend every run key falls back to a recording

Put them in frontend/.env.local (gitignored — copy frontend/.env.example).

Verification gates, all three green on main:

cd frontend
npx pnpm@10 exec tsc --noEmit      # types
npx pnpm@10 test                   # 112 tests
npx pnpm@10 build                  # production build

Deploy your own copy

The frontend is a stock Next 16 app, so any Next host works. On Vercel:

npm i -g vercel
cd frontend
vercel --prod                      # root directory: frontend

Leave NEXT_PUBLIC_DONALD_API unset and the deploy is self-contained: recordings only, no backend, free tier, nothing that can fall over.

Self-hosting the live stack

The live path needs the Go API, MySQL and the MCP server. Everything to run them is in the repo — backend/donald/Dockerfile, the schema in deploy/schema.sql, and the Helm charts in deploy/ for a Kubernetes host. On a PaaS such as Railway or Fly the shape is:

  1. Provision MySQL, load deploy/schema.sql.
  2. Deploy backend/donald/Dockerfile twice from the same image — DONALD_ROLE=api for browsers, DONALD_ROLE=mcp for agents — so a slow agent cannot degrade the graph someone is watching. Config template: deploy/prod.yaml.example.
  3. Set NEXT_PUBLIC_DONALD_API on the frontend to the API's URL and redeploy.
  4. Point your MCP client at the MCP service's /v1/mcp.

Note the backend is generated by nuzur from the v2-run-graph-events model; generated files are listed in .nuzur-codegen-manifest.json and must not be hand-edited. Custom code lives in backend/donald/app/. See backend/donald/AI.md.

Connect a real agent — see skill/README.md. Once your own MCP server is up, add it as a streamable-HTTP server — the demo build ships with no authentication, so put it behind one before exposing it:

{ "mcpServers": { "donald": { "type": "http", "url": "https://<your-mcp-host>/v1/mcp" } } }

Give the MCP client both donald-flow and nauta-operations. Then type any operational request, for example:

“L'Oréal's invoice does not match our PO. Find out what happened and draft the right email.”

The provider in this demo is a real agent reading those skill files. There is no scenario selector: the input is whatever the operator types, the agent chooses its own plan, and the graph is non-deterministic because it is built from the steps the agent actually takes.


The requests that demonstrate the product

Each produces a different shape on screen. That is the proof that the interface comes from the work, not from a script. These are examples, not presets.

Case Example request Shape
It stays quiet “What is the status of OP-4471?” Routine checks collapse into a line. No needless interruption. A system that always shouts is as useless as one that is blind.
It replans and asks “Handle the transshipment on OP-4471.” Unplanned transshipment · $3,780 demurrage exposure · invalidated BL. The graph rewires itself and a decision panel appears.
It crosses domains “Why does L'Oréal's invoice disagree with our PO?” Supplier invoice · missing amendment · exact $840 gap · our error. Different evidence and steps, zero new frontend code.

The third case proves the system is open-ended: it was added by expanding the agent's knowledge, without writing a new flow or changing the frontend.


Why time matters

The steps unfold while a real agent reads, reconciles, calculates and decides what comes next. That is not decorative delay:

Duration is the intervention window. You can only stop something that is still happening. If every step completes instantly, the stop button is decoration.

The graph stays current as the agent works: progress appears when something takes time, a block is visible when the agent needs missing data, and a replan appears the moment new evidence changes the work. The timing belongs to the task, not to a prerecorded sequence.


Documents

docs/donald-architecture.png Deployment and data flow — pods, database, ingress, and the intervention path
docs/donald-domain-model.png The nine entities and their relationships, as modelled in nuzur
PROBLEM.md The operator (Jorge, 52), the thesis, the metric and the anti-scope
DECISIONS.md The engineering decisions, the alternatives we rejected, and why
PITCH.md The pitch script, minute by minute, with the hard Q&A
CONTEXT.md The boundary with Nauta, agent skills and the ui_spec vocabulary
skill/README.md How to connect an agent to Donald over MCP
skill/nauta-operations/SKILL.md The importer world the demo agent can investigate
backend/donald/AI.md Which generated backend files are editable and which are not

Status

The demo is live and permanent; the live stack is self-host.

usedonald.com is the frontend/ directory deployed to Vercel with no backend attached. The five runs replay from bundled recordings through the production reducer and components, so the link cannot go down, cost anything, or drift from the code on main.

✅  frontend deployed, permanent, zero-dependency — the five runs replay from recordings
✅  every run has its own shareable URL, handed to the agent at start_run
✅  donald-flow + nauta-operations skills, ready for any MCP client
✅  Go backend + REST API + MCP server + schema + Helm charts, all in this repo
⚠️  the hosted API and MCP endpoint are OFF — self-host them to get live runs (see above)
⚠️  no authentication in the demo build: anyone who reaches the MCP endpoint can write runs
⚠️  artifact byte uploads need R2 credentials; links and inline text work today
⚠️  demo pacing (`DONALD_DEMO_PACING`) exposes a `wait` tool; turn it off before production

The deployment diagram above describes the live topology — one host, two roles off one image, MySQL behind them. It is what deploy/ builds, and what you get by following Self-hosting the live stack. It is not what serves usedonald.com today.

Surfaces, once the live stack is up

https://usedonald.com/runs/<run_key> one run, watched live
<api>/v1/runs run list, newest first
<api>/v1/runs/<run_key> snapshot + last_sequence
<api>/v1/runs/<run_key>/stream?after=N SSE deltas after a cursor
<mcp>/v1/mcp the agent-facing MCP server

Share the link before the work starts

start_run returns a watch_url, and the skill tells the agent to show it immediately:

Follow along: https://usedonald.com/runs/sess_8f21

The URL is built from the agent's own run_key, so it is known before a single step has run. A link produced at the end is a link nobody opened.

Known limits worth stating plainly

  • Runs recorded before a fix keep the gaps that fix closed. Graph structure is reconstructed from the event log, so a run whose events predate an improvement renders the way it was recorded. Re-run it rather than expecting a repair.
  • Interventions are advisory. The agents are not ours to control, so a stop reaches the agent on its next check_instructions and it complies if it can. That is honest supervision, not a kill switch.
  • Demo pacing is on (DONALD_DEMO_PACING), which exposes a wait tool so runs unfold at a readable speed. It must be turned off before production — an agent should never be able to park a request on the server.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages