Signals
For instructions on how to authenticate to use this endpoint, see API overview.
Endpoints
GET | |
POST | |
PATCH | |
DELETE | |
POST | |
POST | |
GET | |
GET | |
GET | |
POST | |
DELETE | |
GET | |
GET | |
GET | |
POST | |
GET | |
GET | |
POST | |
POST | |
POST |
List all signals scout config
List the per-(team, skill) scout configs for this project. Each row includes its schedule (rolling run_interval_minutes, or a project-local run_cron_schedule when set), enabled, and emit posture. A freshly authored scout skill appears here once its config is registered, either explicitly via create or by the coordinator's next tick.
Required API key scopes
signal_scout:readExample request
GET /api /projects /:project_id /signals /scout /configsExample response
Status 200 Per-scout configs for this project, ordered by skill name.
Create signals scout config
Register the config for a signals-scout-* skill immediately, without waiting for the coordinator to auto-register it. The same call can optionally set run_interval_minutes, a cron run_cron_schedule, enabled, emit, and output destinations. The skill must already exist on this project. Upsert: if a config already exists for the skill, the provided fields are applied to it.
Required API key scopes
signal_scout:writeRequest parameters
- enabledboolean
- emitboolean
- run_interval_minutesinteger
- output_destinations
- run_cron_schedulestringnull
- skill_namestring
Response
Example request
POST /api /projects /:project_id /signals /scout /configsExample response
Status 200 A config already existed for this skill; the provided fields were applied to it.
Status 201 Created config.
Status 400 No such skill on this project, the name lacks the `signals-scout-` prefix, or the project is already at its enabled-scouts maximum.
Update signals scout config
Tune one scout: change its schedule (rolling run_interval_minutes, or a cron run_cron_schedule that takes precedence when set), enabled, or emit (dry-run) posture, or output destinations. skill_name is fixed. Enabling records enabled_by and is activity-logged since it drives spend.
Required API key scopes
signal_scout:writePath parameters
- idstring
Request parameters
- enabledboolean
- emitboolean
- run_interval_minutesinteger
- run_cron_schedulestringnull
- output_destinations
Response
Example request
PATCH /api /projects /:project_id /signals /scout /configs /:idExample response
Status 200 Updated config.
Status 400 Invalid fields, or enabling would exceed the project's enabled-scouts maximum.
Status 404 Config not found for this project.
Delete signals scout config
Delete one scout config by its id, removing the per-(team, skill) schedule/emit row outright. The point is cleaning up an orphaned config whose signals-scout-* skill was archived or deleted — it lingers in list with an empty description, never runs (the coordinator skips it and the skill can't load), but can't otherwise be removed over the API. Deletion is activity-logged. Note: if the skill still exists, the coordinator re-creates a default-schedule config on its next tick — to retire a live scout, archive its skill (or set enabled=false to make it inert) rather than deleting the config.
Required API key scopes
signal_scout:writePath parameters
- idstring
Example request
DELETE /api /projects /:project_id /signals /scout /configs /:idExample response
Status 204 Config deleted.
Status 404 Config not found for this project.
Create signals scout config
Dispatch one on-demand run of this scout immediately, regardless of its schedule. Useful to test a scout right after authoring it, or to refresh its findings on demand. The run executes asynchronously on the worker and inherits every guard the scheduled path has: it is forbidden if scouts are not enabled for the project (403), and skipped if the project is over its Signals credits quota or daily run budget (429) or a run for this scout is already in progress (409). A manual run counts against the same daily run budget as scheduled runs, so repeated manual runs of the same scout can exhaust the project's daily allowance. A manual run does not change the scout's schedule or last_run_at. A disabled scout can still be run this way (to test before enabling). Returns immediately with the workflow id — poll the scout's runs for the result.
Required API key scopes
signal_scout:writePath parameters
- idstring
Response
Example request
POST /api /projects /:project_id /signals /scout /configs /:id /runExample response
Status 202 A run was dispatched. It executes asynchronously; poll the scout's runs for the result.
Status 403 Signals scouts are not enabled for this project.
Status 404 Config not found for this project (or the scout is withheld).
Status 409 A run for this scout is already in progress.
Status 429 The project is over its Signals credits quota or daily scout run budget; try again later.
Create signals scout config
Materialize the scout fleet for this project on demand (idempotent): seed the canonical signals-scout-* skills, create a default-schedule config for any scout lacking one, and return all scout configs. Normally the Temporal coordinator does this on its next tick; this action exists so setup flows (e.g. the wizard's self-driving program) can hand the user a tunable fleet immediately.
Required API key scopes
signal_scout:writeExample request
POST /api /projects /:project_id /signals /scout /configs /syncExample response
Status 200 The team's full scout fleet after the sync, ordered by skill name.
List all signals scout members
Return the people who can review work on this project — one row per member with access to it, each with their user_uuid, email, first_name/last_name, and resolved GitHub login (null when they have no linked GitHub identity). The cold-start reviewer-routing path: when a finding's owner can't be read off a fetched entity's created_by and there's no cached reviewer:<area> memory or inbox precedent, list members, match the owner by email/name, then put their resolved github_login in suggested_reviewers on emit-report / edit-report. Pass search to narrow a large roster; the result is capped at 200. Strictly team-scoped.
Required API key scopes
signal_scout_internal:readQuery parameters
- searchstring
Example request
GET /api /projects /:project_id /signals /scout /membersExample response
Status 200 The project's members, each with their routing identity.
Retrieve signals scout metadata
Return the project's scout metadata: whether it is enrolled, the current announcement banner (e.g. an alpha run-limit notice, or null when unset), and the enforced run limits with current usage. Limits reflect what the coordinator actually applies at dispatch, so a user can see the real throttle rather than what they assume they set. All values come from the signals-scout flag payload, so the banner and caps can change with no deploy.
Required API key scopes
signal_scout:readResponse
Example request
GET /api /projects /:project_id /signals /scout /metadata /currentExample response
Status 200 This project's scout enrollment, announcement banner, and enforced run limits.
List all signals scout notes
Return the steering notes left for this project's scouts, newest first. Pass skill_name to get the notes addressed to one scout plus the general (blank-target) fleet-wide notes — the shape a scout run reads at cold start. Omit skill_name to browse every note. Expired notes are excluded unless include_expired=true. date_from / date_to are a half-open window on created_at (>= date_from, < date_to); pass date_to (the created_at of the oldest note seen) to walk past the cap. Results capped at 500.
Required API key scopes
signal_scout:readQuery parameters
- content_max_charsinteger
- date_fromstring
- date_tostring
- include_expiredbooleanDefault:
false - include_generalbooleanDefault:
true - limitinteger
- skill_namestring
Example request
GET /api /projects /:project_id /signals /scout /notesExample response
Status 200 Matching notes newest-first.
Create signals scout notes
Leave a steering note the scout fleet reads on its next runs. Address it to one scout via skill_name (signals-scout-*), or omit it for a general note every scout sees. Each call creates a new note (no upsert); delete retires one. Attributed to the authenticated user.
Required API key scopes
signal_scout:writellm_skill:writeRequest parameters
- contentstring
- skill_namestring
- expires_atstringnull
Response
Example request
POST /api /projects /:project_id /signals /scout /notesExample response
Status 201 The note as created.
Status 400 Invalid note (empty content, oversized, bad skill_name target).
Delete signals scout notes
Delete one note by its id, retiring it from every scout's view. Use this when a note has been acted on or no longer applies; time-boxed notes can instead carry an expires_at and retire themselves.
Required API key scopes
signal_scout:writellm_skill:writePath parameters
- idstring
Example request
DELETE /api /projects /:project_id /signals /scout /notes /:idExample response
Status 204 Note deleted.
Status 404 Note not found for this project.
Retrieve signals scout project profile
Return the team's deterministic project profile. For the internal scout token the response reflects the newest non-expired cached row or a freshly-built one (lazy compute on cache miss); force_refresh=true skips the cache and rebuilds from authoritative sources. Public read callers (session auth or a signal_scout:read PAK) get the newest cached profile, or 404 if none has been built yet — they never trigger a rebuild. Read this at the start of a run to orient on the team's product mix, integrations, warehouse sources, signal coverage, and existing inbox surface.
Required API key scopes
signal_scout:readQuery parameters
- force_refreshbooleanDefault:
false
Response
Example request
GET /api /projects /:project_id /signals /scout /project_profile /currentExample response
Status 200 The team's current project profile (cached, or freshly built for the internal scout token).
Status 404 No profile has been built for this team yet, and the caller is not the internal scout token (which builds on cache miss). Public read callers never trigger a build.
List all signals scout runs
Return the most recent SignalScoutRun summaries for this project, newest first. Used by the headless scout to dedupe against work other runs already covered. ILIKE matches on summary. date_from / date_to are a half-open window on created_at (>= date_from, < date_to); pass date_to on subsequent calls to walk past the 100-row cap. Pass emitted=true to see only runs that surfaced at least one finding. Pass skill_name (optionally with skill_version) to scope to a single scout. Results capped at 100.
Required API key scopes
signal_scout:readQuery parameters
- date_fromstring
- date_tostring
- emittedbooleannull
- limitinteger
- skill_namestring
- skill_versioninteger
- textstring
Example request
GET /api /projects /:project_id /signals /scout /runsExample response
Status 200 Recent run summaries newest-first.
Retrieve signals scout runs
Return the full SignalScoutRun row. Status, timing, and error flow from the linked tasks.TaskRun. Strictly team-scoped — a UUID belonging to another team returns 404.
Required API key scopes
signal_scout:readPath parameters
- run_idstring
Response
Example request
GET /api /projects /:project_id /signals /scout /runs /:run_idExample response
Status 200 Full run detail.
Status 404 Run not found or not visible to this project.
Create signals scout edit
Rewrite a report's title/summary, append a note, and/or set its suggested reviewers. Can target ANY of the project's inbox reports, not just scout-authored ones — so the edit is attributed to this scout. Setting reviewers is how you rescue a report that surfaced routed to no one: it replaces the reviewer list and re-runs autostart, so a report missing a qualifying reviewer can open a draft PR. Title/summary edits are best-effort: the pipeline may later re-research them.
Required API key scopes
signal_scout_report:writePath parameters
- run_idstring
Request parameters
- report_idstring
- titlestringnull
- summarystringnull
- append_notestringnull
- suggested_reviewersarray
Response
Example request
POST /api /projects /:project_id /signals /scout /runs /:run_id /edit-reportExample response
Status 200 Report edited.
Status 400 Nothing to edit, empty note, or report not found for this project.
Status 404 Run not found for this project.
Retrieve signals scout runs
Return the findings a SignalScoutRun emitted to the inbox, newest first — one row per emit with its description (the finding text as surfaced), weight, confidence, severity, and the deterministic source_id that joins back to the underlying signal. Lets a team and its agents see what a run surfaced without parsing emitted_finding_ids or scanning the signal store. Strictly team-scoped — a run UUID belonging to another team returns 404.
Required API key scopes
signal_scout:readPath parameters
- run_idstring
Example request
GET /api /projects /:project_id /signals /scout /runs /:run_id /emissionsExample response
Status 200 Findings this run emitted to the inbox, newest first.
Status 404 Run not found or not visible to this project.
Retrieve signals scout runs emission
Best-effort reverse of the report -> signals link. For each finding the run emitted, resolve the inbox SignalReport (if any) its underlying signal grouped into by walking the deterministic source_id back through the signal store. report is null when the finding hasn't grouped into a report yet, was de-duplicated away, or its signal was deleted. Lets the scout UI surface which inbox report a finding contributed to — the reverse of the report's evidence list. Strictly team-scoped — a run UUID belonging to another team returns 404.
Required API key scopes
signal_scout:readtask:readPath parameters
- run_idstring
Example request
GET /api /projects /:project_id /signals /scout /runs /:run_id /emissions /reportsExample response
Status 200 Per-finding inbox report links for this run, newest finding first.
Status 404 Run not found or not visible to this project.
Create signals scout emit
The second emit channel: author a complete SignalReport directly instead of emitting a weak signal. The report passes the safety judge, then surfaces at the status the scout's actionability call implies (or is suppressed). Backing evidence is written as bound signals so the report behaves like a pipeline report. NOT idempotent — a retry authors a second report; use reports to find a prior report and edit-report to update it instead.
Required API key scopes
signal_scout_report:writePath parameters
- run_idstring
Request parameters
- titlestring
- summarystring
- evidencearray
- actionability_explanationstring
- actionability
- already_addressedbooleanDefault:
false - repositorystringnull
- priority
- priority_explanationstringnull
- suggested_reviewersarray
Response
Example request
POST /api /projects /:project_id /signals /scout /runs /:run_id /emit-reportExample response
Status 200 Report authored (READY/PENDING_INPUT/suppressed), or skipped by a preflight gate.
Status 400 Invalid report shape (empty title/summary/evidence, bad actionability).
Status 404 Run not found for this project.
Create signals scout emit
Fire emit_signal with source_product = signals_scout. The finding_id is baked into the deterministic Signal.source_id = run:<id>:finding:<id> for traceability, but this is NOT idempotent — a second call with the same finding_id emits a second signal, so do not retry an emit that may have already succeeded.
Required API key scopes
signal_scout_internal:writePath parameters
- run_idstring
Request parameters
- descriptionstring
- confidencenumber
- evidencearray
- hypothesisstringnull
- severity
- dedupe_keysarray
- tagsarray
- time_range
- mcp_trace_idstringnull
- finding_idstringnull
Response
Example request
POST /api /projects /:project_id /signals /scout /runs /:run_id /emit-signalExample response
Status 200 Finding emitted, or skipped by a preflight gate.
Status 400 Invalid emit shape (description, weight, confidence, evidence cap).
Status 404 Run not found for this project.
Create signals scout runs emissions
Batched form of the per-run emissions endpoint: return the findings every requested SignalScoutRun emitted, flattened newest-first, in a single request. Each row carries its run_id, so the caller can regroup by run. The findings UI uses this to load the whole recent window in one round-trip instead of one request per run. Strictly team-scoped — run ids belonging to another team contribute no rows (no per-run 404; one stale id never fails the batch).
Required API key scopes
signal_scout:readRequest parameters
- run_idsarray
Example request
POST /api /projects /:project_id /signals /scout /runs /emissions /batch