How it’s built
The parts you can
check yourself.

Most AI products ask you to trust the output. A production budget doesn’t work that way — an estimate you can’t interrogate is a guess with a decimal point on it. So this page is the architecture, the decisions behind it, and the parts of it you can go and read.

The pipeline
Script in.
Budget out. Then the floor.
01
Parse the script
A PDF goes through screenplay-pdf-to-json and comes back as a breakdown: scene counts, INT/EXT, day/night, the locations that recur, the cast that carry it. No one retypes a slugline.
02
Six questions, generated not fixed
The questions come from your breakdown, so a three-location Mumbai TVC and a single-set music video get asked different things. A fixed form would ask both the same and be wrong for each.
03
Generate the budget
Section-coded the way a producer expects to read it, itemised to the line, with tax handled properly, a confidence marker on every estimate and flags on the lines that need a human eye.
04
Refine in plain English
“Trim catering by two lakh.” “Add a second camera on day three.” The budget changes and stays internally consistent — totals reconcile, the ratios stay sane.
05
Call sheets, in your layout
Upload the call sheet template your productions already use and it renders into that, not into a SaaS export that makes your unit look like someone else’s. Approve it, then it goes out by email and WhatsApp.
06
Estimated against actual
Department by department, live through the shoot. The overrun you can see on day four is a decision. The one you find at wrap is a post-mortem.
Six choices you’d only find
by reading the code.

Every AI product claims to be careful. These are the specific places we spent effort, and what each one cost us.

01
Evals gate the prompt, not just the code

A change to an agent’s instructions can break it as surely as a change to its code, and it breaks silently — the output still looks like a budget. So the prompt has a regression suite.

The invariants are things true of any valid budget: tax is stored as a decimal and not a percentage, the required post sections are present, the post-to-production ratio sits in a sane band, the totals actually reconcile, confidence markers are valid. Golden fixtures hold budgets we’ve reviewed and trust. And there are negative tests that deliberately corrupt a good budget to prove each check fails on the defect it targets — because a test that never fails isn’t a test.

It runs offline in CI on every change, with no API key. After a prompt or rate-card change it runs live against real agent output.

evals/invariants.py · CI gate
02
An irreversible action is two tools, never one

Sending a call sheet messages forty real people. You cannot un-send it, and a wrong unit call costs a shoot day.

So the send is split. propose stages it and returns a preview — it sends nothing. A human approves. confirm executes, and is idempotent, so a retry can’t double-send. To any agent driving MARK these are two separate tools, which means an unattended agent is structurally unable to message a crew in one step. Not discouraged from it. Unable.

propose → approve → confirm
03
Model choice is a latency decision, not a quality one

The synchronous budget path is bound by the browser’s edge timeout, so it runs the fast model and returns while the producer is still sitting there. The async path returns a job you poll, isn’t bound by that timeout, and so requests the stronger model.

Same prompt surface, different constraint. Most products pick one model and make the product fit it. The constraint should pick the model.

/budget/generate/async · job polling
04
Every agent run is a traced span

Model, latency, tokens, whether the cache hit, and what errored. Sent to a proper observability backend when one is configured, and kept in a local ring buffer plus stdout when it isn’t — so tracing degrades rather than disappears.

You cannot improve an estimate whose cost and shape you can’t see. This is also how we know which line items the agent gets wrong most often, which is what the next prompt change is aimed at.

05
One source of truth, many surfaces

The MCP server exposes MARK’s capabilities as typed tools, and every one of them is a thin wrapper over an existing endpoint. No logic is reimplemented at the edge.

The practical effect: a rate-card correction lands in one place, and the web app, the agent harness and anyone driving MARK from their own tooling all get it at the same moment. Duplicated logic is how two surfaces start quoting different numbers for the same shoot day.

06
Agent-native in both directions

Most tools let AI act on your behalf inside their product. MARK does that, and also works the other way: your own agent can drive it. Claude Desktop, Claude Code, Cursor or any MCP client can generate a budget, refine it in plain English, render a call sheet into your template and stage a send for approval.

If a production office already runs its own agent, MARK should be something that agent can call — not another tab someone has to remember to open.

Model Context Protocol
Check it
Claims are cheap.
The repo isn’t.

Everything above is in a public repository. If you want to know whether the eval suite is real rather than a slide, the invariants, the golden fixtures and the negative tests are sitting there to read, and so is the architecture diagram and the MCP tool definitions.

We would rather you checked.

github.com/karanmjpinto/mark ↗

A creative reviews every output before it reaches a producer. The AI does the work nobody wanted to do anyway; the judgement stays with the person whose name is on the call sheet.

The working principle
Roll camera
Start with five days.
Book a teardown →
Five working days · $4,500 fixed · Credited in full against Stage 1