← Building a solo company with AI agents

Part 23 of 40 · 7 min read

The founder’s cockpit and the deployment behind it

Experimental · Work in progress · Internal R&D

Design the founder’s approval inbox and a compact deployment with authenticated access, durable records and operating limits.

Arunank Sharan · Kuzushi Labs ·

In this article

The first screen I want each morning is not a wall of agent conversations. It is a short list of commitments, exceptions and decisions. Which customer is waiting? Which payment needs evidence? What is about to miss its deadline? What will happen if I approve the item in front of me?

The platform already has a FastAPI control-plane surface for summaries, objects, history, events, audit records and human-review tasks. It is a useful local inspection API. Authentication, hardened tenant isolation at every endpoint and production operation of the complete platform remain unfinished.

Organise the screen around decisions

I would give the founder four views:

ViewContentsPrimary action
TodayCommitments due, blocked work and expected receiptsOpen the specific blocking decision
Approval inboxProposed effect, evidence, changed fields and expiryApprove, reject or request clarification
Customer journeyConnected lead, agreement, work, invoice and support stateInvestigate a handoff
Runs and costsAttempts, tools, receipts, versions and operating costReproduce or stop a failing workflow

The approval view should preview the business consequence. For a quote, show the exact version and commercial terms. For a payment, show beneficiary, amount, currency and receipt prerequisites. A generic “Approve agent action” button hides the decision rather than simplifying it.

The local API is not the production security boundary

The existing routes can accept tenant and approver values as request data. Some event and audit access is broader than the tenant-scoped object APIs. Before exposing the service outside a controlled local environment, identity must come from authenticated context and authorisation must filter every read and write.

A proposed request boundary is:

# Design sketch: verified_identity comes from the authentication layer.
tenant_id = verified_identity.active_tenant
principal = verified_identity.as_principal()
assert access_policy.may_review(principal, approval_task)
# Re-read task and target, validate approval binding, then dispatch.

CORS configuration does not supply authentication. Nor should a browser be able to become a human approver simply by sending a different name. The operator surface is a driving interface over the governed backend, not a privileged escape hatch.

Deploy a small number of operational components

For the initial controlled trial, I would keep a compact layout: API/control process, background worker, relational storage, queue/outbox relay, object storage and a model gateway with policy evaluation. The business modules can remain packages in one codebase. Their boundaries are data and action contracts; they do not each need a separately operated service.

The repository's Docker Compose profile covers a model rail and OPA sidecar with configuration and secret injection. It is not a deployment of every loop, worker and cockpit. The platform-wide deployment plan needs to add those components and their operating responsibilities explicitly.

A proposed compact deployment separates public ingress, workers, policy, records and provider adapters.

Persistence changes what failures you can recover from

The local runtime supports in-memory and SQLite object storage, while several event, audit and idempotency components are in-memory in the demonstration paths. Production persistence should cover the whole operation: object mutation, outgoing event, held approval, attempt state and provider receipt.

I would use one relational transaction where possible and write large source documents to object storage with stable hashes. A backup is useful only after a restore test proves that held approvals and uncertain external operations can be reconciled. Restoring yesterday's database must not cause yesterday's payments to be sent again.

A single host can be a reasonable private pilot environment, but it is a single point of failure. Availability and recovery targets should be selected for the chosen business actions, not inferred from the number of containers.

Operate with explicit ceilings

The first trial should have a tenant-level daily spend cap, per-episode step limit, per-connector concurrency limit and a bounded approval queue. A queue older than its commercial deadline should escalate visibly; it should not keep retrying a stale action.

Metrics should include age of the oldest unhandled business event, approval wait time, unresolved external outcomes, duplicate-effect detection, provider error rate and cost per accepted task. Logs should carry correlation and operation IDs so the founder can move from a business exception to technical evidence.

A deployment checklist with a business purpose

Before the first live write, I want an authenticated operator, a real read connector, verified source identity, a bounded action catalogue, durable receipts, a stop control and a demonstrated recovery path. The first action might be updating an internal task rather than contacting a customer or moving money.

The cockpit is successful when it lets one founder supervise the platform without reading every agent turn. That outcome depends as much on a short, well-explained exception queue as it does on the quality of the model.

Design the review screen around the actual decision

The founder should be able to answer four questions without opening a chat transcript: what will happen, who will be affected, what evidence supports it and what changed since the proposal was prepared. A summary such as “approve customer action” is too vague to support informed review.

For a quote, show recipient, scope, price, currency, expiry, delivery assumptions and the exact document revision. For a reminder, show the latest balance and unresolved payment events. For a purchase, show supplier, beneficiary verification, amount and the permitted budget. The same card layout can host different domain-specific evidence.

{
  "action": "send_quote",
  "subject": "opportunity-017",
  "expected_version": 8,
  "recipient": "[email protected]",
  "amount_minor": 600000,
  "currency": "SGD",
  "document_revision": "quote-r3",
  "status": "AWAITING_REVIEW",
  "refresh_required": false
}

This is a proposed public API shape. It describes the decision payload, not an authentication credential. The server must derive actor and tenant identity from the authenticated session rather than trusting fields supplied by the browser.

Make stale review an ordinary interface state

Suppose the founder opens quote revision three, leaves the tab open and returns after the customer negotiates a lower price. The approval request must name the version reviewed. The server should reject stale execution and return the current review packet.

POST /review-actions/action-017/approve
If-Match: "8"
Content-Type: application/json

{"decision_reason":"Scope and delivery window checked"}

A version mismatch can return 409 Conflict with a machine-readable REVIEW_STALE code in this API design. That choice is a contract for this application, not a requirement imposed by HTTP. The UI should preserve the earlier view, highlight the changes and request a fresh decision. It should not silently approve the newest version on the founder's behalf.

The cockpit renders a versioned review packet and refreshes it when the underlying business record changes.

Show uncertainty without making the founder investigate everything

A provider timeout should appear as “delivery status being reconciled,” with the action identity, last attempt and next check. Avoid a second prominent Send button while the first effect is uncertain. An operator can still intervene, but the interface should explain why a retry might duplicate a customer message.

Group the work by business consequence: blocked delivery, unresolved payment, pending commitment and routine draft. Then sort within a group by deadline and age. A chronological stream of every agent event makes the founder the scheduler for the entire company.

Useful controls include pause one loop, stop outbound actions, disable a connector and keep read-only diagnosis available. A global stop must apply at dispatch time as well as when a job is queued. Otherwise already queued work will continue after the interface says the platform is paused.

Keep the operating screen accessible

Use text alongside status colour, readable money and dates, keyboard navigation and a compact explanation of the required decision. Evidence links should land on the relevant record revision. A red badge labelled “failed” is less useful than “payment receipt received; allocation needs review.”

For a solo operator, a morning digest can list only material changes and pending decisions. The digest is a view over persisted state, not the sole record of what happened. Closing or losing the email must not lose the review task.

The exercise is a browser tab left open while another operator changes the quote. Verify that the original approval is refused, the new terms are visible and no provider action has happened. Then simulate a lost acknowledgement and confirm that the UI displays reconciliation rather than inviting an unqualified retry.