SOLWYN

Agent runs

The Agents tab — every run the SDK reported, its lifetime cost and denied cost, velocity flags, and the Stop button that ends a runaway run from outside the process

Every solwyn.run(...) scope, create_run(...) handle, or framework-driven agent that the SDK reports becomes an agent run in Solwyn Cloud. The project's Agents tab lists them, and it is where an operator stops one.

The Agents tab

Open a project and choose Agents. The tab lists runs that were active in the last seven days, each with its lifetime totals — calls, cost, denied cost — so a run that started nine days ago and is still going shows what it has cost since it began, not a window slice. Sort by Most recent, Highest lifetime cost, or Most lifetime calls; the list pages with a cursor.

Expand a run to see when it started and was last seen, its lifetime input and output tokens, and the events it produced in the last seven days — the per-run event list needs a paid plan, and Free sees an upgrade prompt in its place. Two badges can appear on a row:

BadgeMeaning
FlaggedThe SDK's local velocity detector observed a suspicious pattern on this run — the same prompt size repeating, monotonic growth, or a call-rate spike. Hover to see which rules fired. Flags are advisory, derived from the run's reported calls — they ride every cost event, not just denials — and never contain content. See Local velocity detection.
StoppedAn operator stopped the run. Shows when, and by which user id (unknown user when none was recorded).

A ?run= query parameter deep-links to one run. Runs without a caller-supplied id — calls made outside any solwyn.run(...) scope, grouped as _auto-<sdk instance>-<day> — appear in the list but cannot be stopped.

Stopping a run

Press Stop on a run to end it from outside the process. A dialog titled Stop this run? states the contract and is confirmed with Stop run — paraphrased here, because the dialog names the run itself in place of this run:

Solwyn will deny every future budget check for this run and revoke its active budget leases. Requests already in flight are never cut off mid-call: the agent halts at its next budget check or lease renewal — typically within ~15 seconds, at most ~2 minutes. If the agent can't reach Solwyn at all, Solwyn can't block it (it fails open by design); enforcement resumes the moment connectivity does. Spend already in flight still settles. This can't be undone for this run ID.

What happens, in order:

  1. Every later budget check for that run id is denied with denied_by_period: "run_stopped" in hard_deny mode — regardless of the project's mode, so an alert_only project's stop is still a hard stop.
  2. Every active budget lease for the run is revoked. A leased run learns about the stop at its next renewal, which is why the dialog quotes up to about two minutes: the response's enforcement_deadline is the moment the last revoked lease would have expired anyway.
  3. The next intercepted call the SDK makes inside that run raises RunStoppedError, with source="server" and reason="manual_kill". Streams already open are aborted at their next chunk and settle with what they observed. Once the SDK has seen the stop it retains it, so a Solwyn outage afterwards does not let the run resume; a run that never reached Solwyn after the stop simply has not heard it yet.
  4. Stopping is per run id and permanent. There is no un-stop; start a new run.

Stopping requires an owner or admin role. Only runs with a caller-supplied id are stoppable: pressing Stop on an auto-grouped run is disabled, because those calls carry no run id and there is nothing for the SDK to halt — use solwyn.run() scopes to make work stoppable. Each stop writes an agent_run.stopped audit event (readable for 365 days) recording the run name, leases revoked, and the run's cost at the moment of the stop.

The Runaway run alert type surfaces the same button: an alert that fires when a run crosses a spend cap or call rate carries Stop run in the alert sidebar, so the response to a runaway is one click from the notification.

A runaway-run rule in hard_deny mode caps a run's spend server-side and denies further calls with denied_by_period: "agent_run"; it does not stop the run. A stop is always an operator action (or, locally, the SDK's velocity detector). Test either one without a dashboard using FakeControlPlane.stop_run.

Runs in cost analytics

Runs are a first-class dimension of Costs:

  • Group the breakdown by agent run (group_by=agent_run) to see cost per run, with the run name alongside the stored id. Events with no run id fall under (unattributed).
  • Filter events by run with agent_run=<the id your code saw> or agent_run_id=<the stored run_… id> — never both.
  • Denied calls contribute to the run's denied cost and to the project's Saved by Solwyn figure; they are excluded from real spend.

Run grouping (group_by=agent_run) is available on Team and Scale; the agent_run and agent_run_id filters work on every tier.

API

All three endpoints live under /api/v1/projects/{project_id}/agent-runs and take the stored run id (run_ + 32 hex characters), which is what the list returns. Reads accept a project API key or a session token; stop is session-only.

List runs

curl "https://api.solwyn.ai/api/v1/projects/$PROJECT_ID/agent-runs?range=7d&sort=total_cost&limit=25" \
  -H "Authorization: Bearer $SOLWYN_API_KEY"
ParameterMeaning
range7d (default), 30d, 90d, 365d — filtered on the run's last_seen_at. Availability follows the tier's analytics ranges; from and to (timezone-aware RFC 3339, together) set a custom window under the same rules.
qCase-insensitive substring match on the run name.
parentDirect children of one run. Accepts the stored id or the id your code saw. One level only — there is no recursive roll-up.
sortlast_seen_at (default), total_cost, or total_calls; always descending.
limit, cursor1–100 (default 25) and the opaque next_cursor from the previous page. A cursor is bound to its sort.

Each entry carries id, name, parent_run_id, project_id, started_at, last_seen_at, the lifetime total_calls, total_cost, total_denied_cost, total_input_tokens, total_output_tokens, the advisory velocity_flags, and the stop state: stopped_at, stopped_by_user_id, and stoppable. The response also carries next_cursor, has_more, and the effective window.

GET .../agent-runs/{run_id} returns one entry, or 404.

Stop a run

curl -X POST "https://api.solwyn.ai/api/v1/projects/$PROJECT_ID/agent-runs/$RUN_ID/stop" \
  -H "Authorization: Bearer $SOLWYN_ACCESS_TOKEN"

Requires a session token with the budget.write permission (owner or admin). There is no tier gate. The response reports run_id, run_name, stopped_at, already_stopped, leases_revoked, and enforcement_deadline (null when no lease was held). A repeat call is idempotent and answers already_stopped: true with the original stopped_at. An auto-grouped run answers 409 with code run_not_stoppable; an unknown run 404; a control plane that cannot revoke leases 503.

How the stop reaches the SDK

The SDK opts into a run-control directive on every budget check and lease request by sending run_directive_version: "1". When the run is stopped, the denied response carries:

{
  "allowed": false,
  "mode": "hard_deny",
  "denied_by_period": "run_stopped",
  "remaining_budget": 0.0,
  "run_control": {
    "version": "1",
    "action": "terminate",
    "agent_run_id": "<the id the request sent>",
    "reason": "manual_kill"
  }
}

The directive rides only a denied, run_stopped response to a request that opted in; every other response omits it entirely. The SDK verifies that the echoed agent_run_id matches the run it asked about before honoring the directive. The denial receipt it then reports carries deny_source: "server" and deny_reason: "manual_kill", which is where the run's denied cost and the dashboard's stop evidence come from. The full client-side contract is in Run control.

  • Run controlRunStoppedError, sticky stops through outages, and local velocity detection
  • Agent runs in the SDKsolwyn.run, nested runs, tags, and detached handles
  • Alerts — the Runaway run and Scoped budget rule types
  • Budgets — per-run caps and scoped budgets
  • Costs — grouping and filtering spend by run

On this page