report live data - manishiitg/agentworks GitHub Wiki

Live report data from scripts (window.report.run)

Ask about a dashboard item

In a project's dashboard pane, right-click a visible number or text and choose Ask agent about this. You can also select a passage before right-clicking. The question includes the clicked value or selection, its nearby label or table row, the dashboard document and the time it was captured. Existing dashboards get this action automatically.

Choose Where did this come from?, Why hasn't this changed?, or write your own question, then select Send to agent. This uses the project's existing chat, including its queue if the agent is already working. The agent can inspect the dashboard's source and project data to explain the value; the menu itself does not establish its provenance. Copy text is also available; Shift-right-click keeps the browser's own context menu. Touch long-press keeps native selection and copying. Standalone viewing links have no question action; open the project to ask its agent.

A workflow Dashboard normally reads what runs stored in db/db.sqlite (window.report.query). When it needs the current state of an outside system (Notion, a CRM, an API), it can run one of the workflow's own scripts on the server each time the Dashboard loads or someone presses Refresh:

window.report.ready(async () => {
  const out = await window.report.run('code/reports/open_deals.py', { days: 7 });
  render(out);
});

The script prints one JSON value; run resolves with it.

It works on workflow Dashboards and on Crew project Dashboards (the Work product's db/reports/). Crews learn it from the work-dashboard skill, workflows from reporting-policy / design-reporting-ui.

Who can run it, and as whom

  • Crew Dashboards: the crew owner and anyone with the Crew product (Crew Run mode) can trigger its scripts. They run with the crew's selected MCP servers and secrets. Crews have no variables.

  • Anyone who can open the workflow (owner, editor or read-only user) can trigger the scripts its Dashboard calls.

  • The script uses the workflow's or Crew's selection, with the authenticated viewer's live MCP and Vault permissions:

    • its selected MCP servers and tools;
    • its selected secrets ($SECRET_*);
    • its variables ($VAR_*, only when there is a single group; otherwise the defaults).
  • A selected Vault connection must be permitted to the viewer through their groups, including Platform for globally shared connections. Project access alone does not grant Vault MCPs or global secrets. Private MCP credentials remain private to their owner; share a connection through Vault for other Dashboard viewers. Revocation applies to subsequent bridge calls.

  • A report bridge session exists only while its script runs. It has no Vault builder authority and cannot inherit a chat owner's identity.

  • Published static copies cannot run scripts. The publish guidance bakes the output in at publish time, or hides that panel.

The sandbox

Scripts .py (python3) or .js/.mjs (node) under code/; convention code/reports/<name>.py
Args JSON in $REPORT_ARGS ({} when none). Treat them as untrusted input from any viewer.
Output Exactly one JSON value on stdout (at most 2 MB). Logs go to stderr.
Time 60 seconds per call. At most 4 report scripts run at once on a server.
MCP POST $MCP_MCP/<server>/<tool> with the $MCP_AUTH header. Only the workflow's selected servers and tools can be reached.
Database $DB_PATH is a read-only snapshot taken for this call. It is unset if the workflow has no DB yet.
Files Reads anywhere in the workflow. Writes only to $REPORT_CACHE_DIR (<workflow>/.report-cache/), which every viewer shares.

If the script fails (non-zero exit, timeout, non-JSON output), the Dashboard receives the error plus the tail of stderr. Known secret values are redacted from that text.

No platform cache: scripts cache for themselves

Every call runs the script again. The platform keeps no cache, because only the script knows how fresh its data needs to be. Best practices (also in the builder's reporting-policy guidance):

  • Keep one cache file per query in $REPORT_CACHE_DIR, named from the script and its normalized args.
  • Return the cached copy while it is younger than a TTL that suits the source. Include fetched_at so the page can show "as of".
  • Write the cache atomically (temp file, then rename), because two viewers can refresh at the same time.
  • Let a {"refresh": true} arg skip the cache, for the Refresh button.
  • When the upstream call fails but a cache exists, return the cache with stale: true rather than failing.
  • Aggregate in the script, keep every upstream call bounded with a timeout, and never create, update or send anything upstream from a report view.

Validation

validate_report_html() rejects:

  • a window.report.run('…') path that is not a script under code/;
  • a script that does not exist.

preview_report() runs the scripts for real.

Implementation

  • Endpoint: POST /api/workflow/report-preview/run, in agent_go/cmd/server/report_run.go. It lives under the report-preview prefix, so the headless preview's scoped token can reach it.
  • Execution goes through the workspace service's /api/execute, with the same isolator and Folder Guard as scripted steps.
  • MCP scope: each run gets a report-run-<uuid> bridge session. resolveReportRunMCPServer authorizes each call against the workflow manifest's current selection while the script runs. The session is dropped when the script ends.
  • Tests: report_run_test.go, and report_run_e2e_real_test.go (a real workspace service; skipped unless REPORT_RUN_E2E_DOCS is set).
⚠️ **GitHub.com Fallback** ⚠️