Skip to main content

Projects

A project is your persistent configuration: which repos to clone, what budgets to enforce, and when to run. All LLM calls use Synth-managed keys. Every run is executed against a pinned snapshot of that config, so you can always trace which configuration produced which results. Project state lives at GET /smr/projects/{project_id}. Key fields:
{
  "project_id": "...",
  "name": "my-research-project",
  "repos": ["github.com/your-org/your-repo"],
  "key_policy": { "mode": "synth_only" },
  "budgets": { "monthly_usd_cents": 5000, "run_usd_cents": 1000 },
  "onboarding_state": { "status": "complete" },
  "active_config_version_id": "..."
}

Onboarding

The run button is disabled until onboarding is complete. The wizard has four steps:
StepWhat it does
1. Project basicsName, timezone, schedule window (at /smr/new)
2. Connect GitHubOAuth or PAT → workers use this credential to clone and push. Optional; can skip.
3. Starting data & specUpload datasets, example traces, or other references the agents should use. Write the project spec (what agents should research).
4. BudgetsSet monthly + per-run caps, timebox (max run duration); run dry-run validation
Artifact storage defaults to Synth S3 — no customer AWS setup. Backend step keys: connect_github, starting_data_spec, keys_budgets, plus artifact_storage, approvals_egress, notifications when used via API. Check status at GET /smr/projects/{project_id}/onboarding/status. Run the dry-run check at POST /smr/projects/{project_id}/onboarding/dry_run — it validates Infisical reachability, provider key presence, and S3 write access.

Entitlements

Managed Research requires a Pro or Team plan. Check entitlement at GET /smr/projects/{project_id}/entitlements/managed_research. The frontend shows “SMR Access: Enabled” or “Upgrade to Pro” based on this.

Runs

A run is a single execution against a config snapshot. Trigger one at POST /smr/projects/{project_id}/trigger.

Run states

queued → planning → executing → [blocked] → finalizing → done
                                                        ↘ failed
                                                        ↘ stopped
  • queued — waiting for the orchestrator to claim it
  • planning — orchestrator has claimed it and is creating tasks
  • executing — one or more worker tasks are in progress
  • blocked — waiting on a pending approval
  • finalizing — workers done, assembling proof bundle and summary
  • done — complete; all artifacts are available
  • failed — terminated with an error; partial artifacts may exist
  • stopped — timebox hit, budget exhausted, or manual stop
blockedexecuting is automatic once the blocking condition resolves. You can pause a project at any time; the orchestrator stops and state is preserved. Resume when ready.

Run options

When triggering, you can override:
{
  "timebox_seconds": 28800,
  "agent_model": "gpt-5.2",
  "agent_kind": "codex"
}
agent_kind must be one of codex, claude, or opencode.

Tasks and workers

Orchestrators and workers are coding agents that create, assign, complete, and update tasks. They work towards a set of deliverables you can review once the run is over.

Artifacts

Artifacts are typed, immutable outputs produced during a run. Every artifact has a stable URI and a content digest.
TypeContents
report_mdMarkdown report generated by workers — rendered first-class on the Deliverables page
github_prPull requests opened on your repo(s) — links with status in the Deliverables page
Result filesArbitrary files workers attach via create_artifact — downloadable with content preview
Download content at GET /smr/artifacts/{artifact_id}/content. List all artifacts for a run at GET /smr/projects/{project_id}/runs/{run_id}/artifacts.

Budgets

FieldEnforced whereWhat happens when hit
run_usd_centsData planeRun stops with stop_reason: budget_exhausted
monthly_usd_centsControl planeNew runs blocked until next calendar month
Both are hard stops, not soft warnings. Set timebox_seconds when triggering a run to cap duration; when hit, the run stops with stopped. Check current spend at GET /smr/projects/{project_id}/usage — it returns MTD and last-7-days totals broken down by provider.

Approvals

When a worker wants to take a sensitive action (e.g. push a PR, write plaintext externally), it creates an approval request and the run moves to blocked.
  • List: GET /smr/projects/{project_id}/runs/{run_id}/approvals
  • Approve: POST /smr/runs/{run_id}/approvals/{approval_id}/approve
  • Deny: POST /smr/runs/{run_id}/approvals/{approval_id}/deny

Orchestrator health

The orchestrator heartbeats every few minutes. If last_heartbeat_at is more than 5 minutes stale and there’s an active run, the UI shows Unhealthy. At 30 minutes stale it turns red. Check via GET /smr/projects/{project_id}/ops_statusorchestrator.status will be running, idle, or unhealthy.