Operators API
An operator is a named AI worker: it senses through connectors, reasons with a base model toward the outcome you wrote for it, and proposes execution plans. This page documents creating, listing, updating, pausing, and resuming operators. What an operator is conceptually is covered in Operators.
Shared conventions, including authentication, pagination, the Idempotency-Key header, and the error envelope, are defined in the API overview. Error codes are catalogued in Errors.
The operator object
Unique identifier, prefixed op_.
Always operator.
Slug-style name, unique within the tenant, for example order-risk. Immutable after creation; the name is the operator's identity in receipts.
One of active, paused, or draft. A paused operator stops reasoning and proposing; events keep ingesting.
The outcome prompt: a plain-language statement of what the operator is accountable for. This is what the base model reasons toward on every run.
Capabilities the operator may propose, named by intent in noun.verb form, for example order.hold. Which connector fulfills each capability is configuration; see Capabilities.
Trust-policy rules evaluated by the deterministic executor. Each rule has optional connector and tool matchers (omitted means any), an optional max_value ceiling, and a decision of ALLOW or ALERT. The policy is default-closed: a side-effecting action with no matching rule is blocked. See Governance & trust.
Base model the operator reasons with. Defaults to the tenant's configured model router.
Optional cron expression for cadence runs. null means event-driven only.
RFC 3339 timestamp of creation.
Summary of the most recent run: run_id, counts of events sensed, actions proposed and applied, and the timestamp at. null before the first run.
{
"id": "op_8f2a1c",
"object": "operator",
"name": "order-risk",
"status": "active",
"outcome": "No order misses its promised ship date without a hold and a reason on the record.",
"capabilities": ["order.read", "order.hold", "order.notify"],
"guardrails": [
{ "tool": "order.hold", "decision": "ALLOW", "max_value": 500 },
{ "tool": "order.notify", "decision": "ALERT" }
],
"model": "router:default",
"schedule": "*/15 * * * *",
"created_at": "2026-06-10T14:21:03Z",
"last_run": {
"run_id": "run_5b21",
"sensed": 42,
"proposed": 3,
"applied": 2,
"at": "2026-07-02T15:02:11Z"
}
}
An operator can sense and propose the moment it is active. Nothing it proposes runs until the deterministic executor evaluates each action against the guardrails, which fail closed: no matching rule means BLOCK. An operator created with an empty guardrails array can read but can execute no side effect at all.
List operators
operators:readReturns operators for the authenticated tenant, newest first, cursor-paginated.
Filter by active, paused, or draft. Omit to return all.
Only operators granted this capability, for example order.hold.
Page size, 1–100. Defaults to 20.
Pagination cursor from a previous response's next_cursor.
curl "https://api.fibric.io/v1/operators?status=active" \
-H "Authorization: Bearer $FIBRIC_KEY"
{
"object": "list",
"data": [
{
"id": "op_8f2a1c",
"object": "operator",
"name": "order-risk",
"status": "active",
"capabilities": ["order.read", "order.hold", "order.notify"],
"created_at": "2026-06-10T14:21:03Z"
}
],
"has_more": false,
"next_cursor": null
}
Create an operator
operators:writeRegisters a named worker with its capability requirements, its outcome prompt, and its guardrails. Creation fails with 422 capability_unbound if a requested capability is fulfilled by no installed connector; install one first through the Connectors API.
Slug-style name, unique within the tenant. Lowercase letters, digits, and hyphens; 3–40 characters.
The outcome prompt the operator reasons toward. Write it as an accountable statement, not a task list.
Capabilities the operator may propose, in noun.verb form. Every entry must be fulfilled by an installed connector.
Trust-policy rules: connector (optional matcher), tool (optional matcher), max_value (optional numeric ceiling, compared against an action's value), and decision (ALLOW or ALERT). Defaults to an empty array, which blocks every side effect.
Base model override. Defaults to the tenant's configured router.
Cron expression for cadence runs. Omit for event-driven only.
active or draft. Defaults to active.
curl -X POST https://api.fibric.io/v1/operators \
-H "Authorization: Bearer $FIBRIC_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: op-create-order-risk" \
-d '{
"name": "order-risk",
"outcome": "No order misses its promised ship date without a hold and a reason on the record.",
"capabilities": ["order.read", "order.hold", "order.notify"],
"guardrails": [
{ "tool": "order.hold", "decision": "ALLOW", "max_value": 500 },
{ "tool": "order.notify", "decision": "ALERT" }
],
"schedule": "*/15 * * * *"
}'
{
"id": "op_8f2a1c",
"object": "operator",
"name": "order-risk",
"status": "active",
"outcome": "No order misses its promised ship date without a hold and a reason on the record.",
"capabilities": ["order.read", "order.hold", "order.notify"],
"guardrails": [
{ "tool": "order.hold", "decision": "ALLOW", "max_value": 500 },
{ "tool": "order.notify", "decision": "ALERT" }
],
"model": "router:default",
"schedule": "*/15 * * * *",
"created_at": "2026-07-02T15:01:00Z",
"last_run": null
}
Error cases:
| Status | Code | When |
|---|---|---|
400 | missing_parameter | name, outcome, or capabilities is absent. |
400 | invalid_parameter | name is not a valid slug, a capability is not noun.verb, or a guardrail's decision is not ALLOW or ALERT. |
409 | state_conflict | An operator with this name already exists in the tenant. |
422 | capability_unbound | A requested capability is fulfilled by no installed connector. The message names it. |
Retrieve an operator
operators:readReturns the full operator object, including its guardrails and last run summary.
The operator id, for example op_8f2a1c.
curl https://api.fibric.io/v1/operators/op_8f2a1c \
-H "Authorization: Bearer $FIBRIC_KEY"
Returns the operator object. A cross-tenant id reads as 404 not_found.
Update an operator
operators:writeUpdates the fields you send and leaves the rest untouched. name is immutable. Guardrail changes take effect on the next plan the executor evaluates; a plan already disposed keeps the verdicts it received. Guardrail edits are themselves recorded in the audit trail.
Replace the outcome prompt.
Replace the capability set. Each entry is validated against installed connectors, the same as at creation.
Replace the full rule set. This is a whole-value replace, not a merge; send every rule you want to keep.
Change the base model or set router:default.
Change the cadence, or null to make the operator event-driven only.
curl -X PATCH https://api.fibric.io/v1/operators/op_8f2a1c \
-H "Authorization: Bearer $FIBRIC_KEY" \
-H "Content-Type: application/json" \
-d '{
"guardrails": [
{ "tool": "order.hold", "decision": "ALLOW", "max_value": 1000 },
{ "tool": "order.notify", "decision": "ALERT" }
]
}'
Returns the updated operator object.
Error cases:
| Status | Code | When |
|---|---|---|
400 | invalid_parameter | A field failed validation, including an attempt to change name. |
404 | not_found | No operator with this id exists for the tenant. |
422 | capability_unbound | An updated capability is fulfilled by no installed connector. |
Pause an operator
operators:writeMoves the operator to paused. A paused operator stops reasoning and stops proposing; scheduled runs are skipped. Events keep ingesting so nothing is lost, and plans it already proposed remain visible and approvable in the Actions & plans API. Pausing an already-paused operator is a no-op and returns 200.
The operator to pause.
Optional note recorded in the audit trail alongside the pause.
curl -X POST https://api.fibric.io/v1/operators/op_8f2a1c/pause \
-H "Authorization: Bearer $FIBRIC_KEY" \
-H "Content-Type: application/json" \
-d '{ "reason": "warehouse inventory count this weekend" }'
{
"id": "op_8f2a1c",
"object": "operator",
"name": "order-risk",
"status": "paused",
"paused_at": "2026-07-02T18:30:00Z"
}
Resume an operator
operators:writeMoves a paused operator back to active. The operator resumes on the next matching event or the next scheduled tick; it does not replay events that arrived while paused unless you pass catch_up.
The operator to resume.
When true, the operator reasons over events that ingested while it was paused, oldest first. Every plan that results still goes through the executor. Defaults to false.
curl -X POST https://api.fibric.io/v1/operators/op_8f2a1c/resume \
-H "Authorization: Bearer $FIBRIC_KEY" \
-H "Content-Type: application/json" \
-d '{ "catch_up": true }'
{
"id": "op_8f2a1c",
"object": "operator",
"name": "order-risk",
"status": "active",
"resumed_at": "2026-07-02T19:05:00Z",
"catch_up_events": 17
}
Error cases for pause and resume:
| Status | Code | When |
|---|---|---|
404 | not_found | No operator with this id exists for the tenant. |
409 | state_conflict | Resuming an operator in draft. Activate it with PATCH first. |
Operators from the marketplace, such as op-order-sentinel (Order Risk), install as packaged workers with their capabilities and outcome already defined. They appear in this API like any other operator and can be paused, resumed, and re-guarded the same way, but their outcome and capabilities are managed by the pack. See Operator packs.