Agent Workflow Cookbook
This cookbook walks through the full “plain English to production model” workflow. Each step shows the prompt you can send to your MCP-compatible AI agent, the Bridge Town tool call it should make, a representative response, and the model code or output shape to expect.
Prerequisites
Section titled “Prerequisites”- A Bridge Town account at app.bridgetown.builders
- Claude, Codex, Gemini, or another MCP-compatible client connected to Bridge Town (see Quick Start)
- Editor or Owner role on the workspace
Step 1: Create a project
Section titled “Step 1: Create a project”Prompt to your agent:
Create a new project called
revenue-forecastfor a 12-month revenue model.
MCP tool call:
{ "name": "create_project", "arguments": { "project_name": "revenue-forecast", "description": "12-month revenue forecast with three product lines" }}Representative response:
{ "project": "revenue-forecast", "description": "12-month revenue forecast with three product lines", "org": "acme", "clone_url": "https://git.bridgetown.builders/acme/revenue-forecast.git", "gitea_id": 128, "run_py": "\"\"\"Bridge Town model entry point.\"\"\"\n...", "model_py": "\"\"\"Starter financial model.\"\"\"\n..."}run_py and model_py contain the default scaffold when scaffold is omitted or true. If you pass "scaffold": false, both fields are null.
Step 2: Create your first model
Section titled “Step 2: Create your first model”Prompt to your agent:
In the
revenue-forecastproject, create a model calledforecastthat projects 12 months of revenue for three product lines: SaaS starting at $50k per month with 8% monthly growth, Services starting at $30k per month with 3% monthly growth, and Marketplace starting at $15k per month with 12% monthly growth. Write chart-ready output and a summary.
MCP tool call:
Use the Python code below as the content string.
{ "name": "create_file", "arguments": { "project_name": "revenue-forecast", "path": "model/forecast.py", "content": "<paste the Python code shown below>", "commit_message": "feat: add 12-month revenue forecast model" }}Model code (model/forecast.py):
"""12-month revenue forecast with chart-ready outputs."""import jsonfrom pathlib import Path
MONTHS = 12LINES = { "SaaS": {"base": 50_000, "growth": 0.08}, "Services": {"base": 30_000, "growth": 0.03}, "Marketplace": {"base": 15_000, "growth": 0.12},}
results = {}for name, params in LINES.items(): monthly = [] revenue = params["base"] for _month in range(MONTHS): monthly.append(round(revenue, 2)) revenue *= 1 + params["growth"] results[name] = monthly
chart_data = { "x": [f"2026-{month:02d}" for month in range(1, MONTHS + 1)], "series": [ {"name": name, "values": values} for name, values in results.items() ],}summary = { "line_totals": { name: round(sum(values), 2) for name, values in results.items() }, "total_revenue": round(sum(sum(values) for values in results.values()), 2),}
Path("/outputs/chart_data.json").write_text(json.dumps(chart_data, indent=2))Path("/outputs/summary.json").write_text(json.dumps(summary, indent=2))
print("12-Month Revenue Forecast")print("=" * 40)for name, values in results.items(): total = sum(values) print(f"{name:12}: ${total:>12,.2f}")print("=" * 40)print(f"{'Total':12}: ${summary['total_revenue']:>12,.2f}")Representative response:
{ "path": "model/forecast.py", "project": "revenue-forecast", "commit_sha": "abc1234def5678901234567890abcdef12345678"}Step 3: Run the model
Section titled “Step 3: Run the model”Prompt to your agent:
Run the
revenue-forecastproject.
MCP tool call:
{ "name": "run", "arguments": { "scope": "project", "mode": "sync", "project_name": "revenue-forecast" }}Representative response:
{ "run_id": "2f9e8a5b-31d4-4a2d-9ef0-8b8e7f3a2c91", "project": "revenue-forecast", "branch": "main", "commit_sha": "abc1234def5678901234567890abcdef12345678", "status": "success", "exit_code": 0, "stdout": "12-Month Revenue Forecast\n========================================\nSaaS : $ 948,856.32\nServices : $ 425,760.89\nMarketplace : $ 361,997.00\n========================================\nTotal : $1,736,614.21\n", "stderr": "", "stdout_truncated": false, "stderr_truncated": false, "outputs": { "chart_data.json": { "x": ["2026-01", "2026-02", "2026-03"], "series": [ {"name": "SaaS", "values": [50000.0, 54000.0, 58320.0]}, {"name": "Services", "values": [30000.0, 30900.0, 31827.0]}, {"name": "Marketplace", "values": [15000.0, 16800.0, 18816.0]} ] }, "summary.json": { "line_totals": { "SaaS": 948856.32, "Services": 425760.89, "Marketplace": 361997.0 }, "total_revenue": 1736614.21 } }, "duration_seconds": 1.23, "data_snapshot_ref": null, "error": null}Step 4: Inspect outputs
Section titled “Step 4: Inspect outputs”The run response contains three values you usually need:
stdoutfor a quick human-readable summaryoutputsfor files written to/outputs/run_id, a UUID you can pass toget_run_output,get_run, or dashboard tools
To fetch one output from a completed run, prefer get_run_output. It avoids
pulling the full run envelope and supports individual outputs up to 10 MiB:
{ "name": "get_run_output", "arguments": { "run_id": "2f9e8a5b-31d4-4a2d-9ef0-8b8e7f3a2c91", "output_name": "summary.json", "encoding": "auto" }}To retrieve a past run:
{ "name": "get_run", "arguments": { "run_id": "2f9e8a5b-31d4-4a2d-9ef0-8b8e7f3a2c91" }}Step 5: Patch assumptions
Section titled “Step 5: Patch assumptions”After reviewing the base case, test a higher SaaS growth scenario.
Prompt to your agent:
Bump the SaaS growth rate from 8% to 12% per month in the
forecastmodel.
MCP tool call:
{ "name": "patch_file", "arguments": { "project_name": "revenue-forecast", "path": "model/forecast.py", "find_text": " \"SaaS\": {\"base\": 50_000, \"growth\": 0.08},", "replace_text": " \"SaaS\": {\"base\": 50_000, \"growth\": 0.12},", "expected_occurrences": 1, "commit_message": "feat: raise SaaS growth assumption to 12%" }}Representative response:
{ "path": "model/forecast.py", "project": "revenue-forecast", "commit_sha": "bcd2345ef678901234567890abcdef123456789a", "replacements_applied": 1}Step 6: Rerun and compare
Section titled “Step 6: Rerun and compare”Prompt to your agent:
Rerun the project and show me the new totals.
MCP tool call:
{ "name": "run", "arguments": { "scope": "project", "mode": "sync", "project_name": "revenue-forecast" }}Representative stdout from the patched model:
12-Month Revenue Forecast========================================SaaS : $1,206,656.66Services : $ 425,760.89Marketplace : $ 361,997.00========================================Total : $1,994,414.55The SaaS line increased from $948,856.32 to $1,206,656.66, a $257,800.34 scenario delta.
Step 7: Create a dashboard
Section titled “Step 7: Create a dashboard”Turn the chart output into a line chart. The important detail is that output_key must select an object that directly matches the chart schema. Because the model wrote /outputs/chart_data.json with top-level x and series keys, use "output_key": "chart_data.json".
Prompt to your agent:
Create a dashboard called
revenue-chartfrom run2f9e8a5b-31d4-4a2d-9ef0-8b8e7f3a2c91, using thechart_data.jsonoutput.
MCP tool call:
{ "name": "create_dashboard", "arguments": { "project_name": "revenue-forecast", "dashboard_name": "revenue-chart", "chart_type": "line", "model_run_id": "2f9e8a5b-31d4-4a2d-9ef0-8b8e7f3a2c91", "output_key": "chart_data.json", "description": "12-month revenue forecast by product line", "subtitle": "Base case - April 2026 assumptions" }}Representative response:
{ "dashboard_id": "7c0e7229-b05e-4548-a067-76e2afda77b9", "dashboard_name": "revenue-chart", "project": "revenue-forecast", "chart_type": "line", "model_run_id": "2f9e8a5b-31d4-4a2d-9ef0-8b8e7f3a2c91", "has_html": true, "created": true, "created_at": "2026-04-28T10:00:00+00:00", "updated_at": "2026-04-28T10:00:00+00:00"}Step 8: Share the dashboard
Section titled “Step 8: Share the dashboard”Generate a time-limited, anonymous share URL. This requires a Pro plan.
Prompt to your agent:
Share the
revenue-chartdashboard for 72 hours.
MCP tool call:
{ "name": "share_dashboard", "arguments": { "project_name": "revenue-forecast", "dashboard_name": "revenue-chart", "expires_hours": 72 }}Representative response:
{ "dashboard_name": "revenue-chart", "project": "revenue-forecast", "share_url": "https://s3.bridgetown.builders/dashboards/revenue-chart.html?X-Amz-Expires=259200", "expires_hours": 72, "embed_snippet": "<iframe\n src=\"https://s3.bridgetown.builders/dashboards/revenue-chart.html?X-Amz-Expires=259200\"\n title=\"revenue-chart\"\n width=\"100%\"\n height=\"600px\"\n frameborder=\"0\"\n allowfullscreen\n></iframe>"}Paste the share_url into Slack, email, or a Notion doc. Paste the embed_snippet into an internal wiki or CMS.
Variation: Import data from Google Sheets first
Section titled “Variation: Import data from Google Sheets first”If your assumptions live in a Google Sheet rather than hard-coded constants, follow this pre-modeling flow:
- Connect the sheet through OAuth in the web app.
- Import the assumptions tab.
{ "name": "connect_google_sheet", "arguments": { "sheet_url": "https://docs.google.com/spreadsheets/d/ABC123/edit", "project_name": "revenue-forecast", "tab_names": ["Assumptions"] }}- Query the snapshot to verify the import.
{ "name": "query_data", "arguments": { "project_name": "revenue-forecast", "sql": "SELECT * FROM revenue_forecast_Assumptions" }}- Update the model to read from
/data/at runtime instead of using hard-coded constants. - Export results back after the run with
write_gsheet(spec.mode="replace"orspec.mode="append").
See the full Google Sheets Integration guide for step-by-step screenshots, formatting presets, and scheduled refresh.
Variation: Branch, review, and merge
Section titled “Variation: Branch, review, and merge”For production workflows, avoid patching main directly. Use branches and pull requests.
1. Create a scenario branch
Section titled “1. Create a scenario branch”{ "name": "create_branch", "arguments": { "project_name": "revenue-forecast", "branch_name": "scenario/aggressive-saas", "base_branch": "main" }}2. Patch the model on the branch
Section titled “2. Patch the model on the branch”Repeat Step 5 but add "branch": "scenario/aggressive-saas" to the patch_file call.
3. Run the branch
Section titled “3. Run the branch”Repeat Step 6 but add "branch": "scenario/aggressive-saas" to the run call.
4. Open a pull request
Section titled “4. Open a pull request”{ "name": "create_pull_request", "arguments": { "project_name": "revenue-forecast", "title": "Raise SaaS growth to 12%", "head_branch": "scenario/aggressive-saas", "body": "Increases SaaS monthly growth from 8% to 12% based on updated pipeline assumptions." }}5. Review and merge
Section titled “5. Review and merge”A teammate approves with review_pull_request, then an Owner merges with merge_pull_request.
See the Team Collaboration guide for full details on roles, notifications, and templates.
Complete tool-call sequence
Section titled “Complete tool-call sequence”| Step | Tool | Key arguments |
|---|---|---|
| 1 | create_project | project_name, description |
| 2 | create_file | project_name, path, content |
| 3 | run | scope: project, mode: sync, project_name |
| 4 | get_run_output | run_id, output_name |
| 5 | patch_file | project_name, path, find_text, replace_text |
| 6 | run | Same as Step 3 |
| 7 | create_dashboard | project_name, dashboard_name, chart_type, model_run_id, output_key |
| 8 | share_dashboard | project_name, dashboard_name, expires_hours |
What’s next
Section titled “What’s next”- MCP Tools Reference - browse every tool parameter
- Dashboards - learn all supported chart schemas
- Google Sheets Integration - import, model, export
- Team Collaboration - branches, PRs, and reviews
- Multi-Model Pipelines - chain models with
/upstreampassing - Sandbox Execution - security model and container boundaries