Automate

Connect an external agent (MCP)

If you already work in an AI coding agent of your own, you can point it at VeriRun Lab over MCP (the Model Context Protocol) and drive your research from there — read runs, size a data window, launch and poll backtests, and stage workspace edits. Crucially, it gets exactly the capabilities you grant it and not one more: every platform gate is enforced on the server, so an external agent is never a way around the rules.

What this is (and isn't)

This is the same read → propose → check philosophy as the in-app AI Assistant, exposed to a client you run yourself. It is a research surface: your agent can look at a lot and it can propose changes and launch runs, but it cannot approve spend, accept its own proposals, or touch entitlements — those verbs simply do not exist on this interface. Anything that would cost money or change state still needs a human in the app.

No MCP client? There is a simpler round trip: the workspace's Download runnable .zip export packs an AI_INSTRUCTIONS.md with the working rules and SDK contract an external AI needs to edit the code, plus the exact re-package steps — so any assistant can work on the zip and hand it back for Import .zip from AI, where it lands as a reviewable import, not an applied change.

Setup

  1. Mint a machine token. In the app, go to Settings → Agent access and issue a token. It requires a fresh code from your authenticator, and it is scoped: you choose which permissions it carries and which projects it can see. The token value is shown once — copy it then.
  2. Give it to your agent. Store the token as the VERIRUNLAB_MACHINE_TOKEN environment variable in your MCP client's config. Most MCP-capable coding agents read a small JSON config; a typical entry looks like:
{
  "mcpServers": {
    "verirunlab": {
      "command": "uv",
      "args": ["run", "--package", "verirunlab-mcp", "verirunlab-mcp"],
      "env": {
        "VERIRUNLAB_MACHINE_TOKEN": "vrl_…",
        "VERIRUNLAB_API_URL": "https://api.verirunlab.com"
      }
    }
  }
}

That runs the connector as a local subprocess your agent talks to over stdio — the usual local-config model. It can also run as a shared HTTP service if you'd rather host it once for a team. Either way, authentication, the available tools, and every server-side gate are identical; only the wire changes.

Scopes decide what a token can do

When you issue a token you pick from a fixed list of permissions — read runs, launch runs, read workspace files, propose edits, write run notes — and the specific projects it can see. Read permissions never move money or change state. A token is scoped to its projects at mint time and can't be edited afterwards: a tool call against a project the token doesn't carry returns a 404 by design, and to add a project you mint a fresh token. Tokens can carry an optional expiry and can be revoked at any time from the same settings page; a revoked token stops working within a minute.

Finding the IDs your agent needs

The tools address things by ID — a project_id, workspace_id or run_id. Usually the only one you have to hand over is the project id: from there the agent can discover the rest itself with list_workspaces(project_id) (the project's workspaces) and list_plugin_versions(workspace_id) (each workspace's cut strategy versions, with their approval state — what run_backtest needs — and the same declaration warnings the version card shows in the app, e.g. a declared feature key the run mount will exclude). Those same warnings also come back on every code proposal your agent submits, so it sees them the moment it writes the code, not first on the dashboard.

To read an ID manually: the app URL — a project lives at /app/projects/<id>, a workspace at /app/workspaces/<id>, and a run at /app/runs/<id>. The project and workspace headers also carry a Copy ID button, so you can grab one without parsing the address bar. And because every /agent response carries a resolvable dashboard_url deep link, once your agent has touched something it can hand the exact page — ID and all — straight back to you.

The read surface — never spends

A broad set of read-only tools lets your agent gather context before it does anything that costs credits. None of these consume anything:

  • Runs & results — list and poll runs, read a run's scorecard summary, manifest, artifact index, and the regime, stress and price-path robustness views; compare runs.
  • Prior research — optimization studies, their leaderboards and trials; screener sweeps and the instruments a sweep can fan across.
  • Data sizing — the instrument list, dataset coverage, and stored data quality reports, so an agent can judge whether a window is trustworthy before it enqueues a run.
  • Context — prop-firm rules and evaluations, your journal trades, and the community leaderboard.
  • Catalogs — the feature primitives and workspace templates, plus a read of any workspace file.

The acting surface — gated, and cheap-first

The tools that do something follow the same validate-before-you-spend rhythm the app encourages:

  • Run the checks in order — tests, then a significance preview, then a preview, then a full backtest — polling each with the backoff the response suggests. Tests and previews are free; backtests are metered. Plugin-version launches take an explicit session window (window_start/window_end, YYYY-MM-DD) and optional params for the version's params_schema — omitted keys keep the schema defaults, and unknown keys are refused at enqueue. The launch dialog's execution-venue and execution-semantics settings are deliberately human-only controls and don't exist on this surface.
  • Propose edits as drafts. A workspace write lands as an inert draft proposal, exactly like the in-app Assistant. It collects in the AI-drafts inbox (/app/drafts), where a human opens it and accepts it per scope: a button appears for each kind of change the proposal actually contains — production code, test content, and the test setup that runs around the tests — one decision each, and the draft stays in the inbox until every scope it contains has been decided. The agent can never assume acceptance.
  • Write conclusions back to a run's notes, and request a shareable report bundle for a finished run (a packaging step that derives no new evidence).

Every response carries a resolvable dashboard_url deep link back into the dashboard, so anything your agent did is one click away in the UI — and agent-launched runs are stamped so you can tell them apart from your own.

Refusals are the system working

If the connector returns a refusal — tests aren't green yet, a proposal is still waiting on a human, a spend needs approval, a daily quota is reached — that is a gate doing its job, enforced on the server where a token can't talk its way past it. The right response is to report it and adapt, never to retry-hammer or route around it.