Skip to main content
Polycore treats approval and audit as part of the execution path, not optional logging added by each integration.
  • Your access policy decides which invocations dispatch immediately.
  • Invocations your policy holds require an approval record before dispatch.
  • Approval or denial applies to one exact invocation.
  • Every outcome is recorded under the original user-facing request.

The approval gate

Agents and unprivileged callers do not receive a tool that can turn a pending request into an approved one. The human decision arrives through a separate approval surface.

What your policy is

Code in your runner repository. There is no rule builder and no JSON: a policy is a function that receives one invocation and returns a decision.
because is shown to whoever approves and stored on the audit record, so write it as the sentence you would want an approver to read. An action carries its own policy in its own file, next to the code it governs, and reads that action’s typed input:
The capabilities Polycore ships have no file of yours to live in, so their policy goes in policy.ts at the runner package root:
Every policy also sees environment (the environment the call is dispatched to) and via ("human" or "agent").
A capability with no policy falls to its hazard: reads dispatch, writes and delegated code wait for a human. Writing no policy at all changes nothing.
A never is an answer, not a step toward one. Nothing is recorded as pending and no approver is asked, so it cannot be released by clicking a button.

Gating on effect, not on arguments

Most capabilities name their target in their arguments, so a policy reads input. A SQL predicate does not: update orders set status = 'x' where … names its rows only when it is evaluated. So Postgres writes preview themselves. The statement is rewritten into a read that reports the exact rows it would change, the columns it would assign, and every table a foreign key would carry it into. Your policy decides on that:
An agent can then write whatever SQL the task needs. A small, in-scope status change dispatches; the same statement against a different table, or touching two thousand rows, waits for a human who sees the actual row diff. The invocation that runs is the one that was previewed. Approval dispatches the previewed rows by primary key, matched on the version each row had at preview time, so a row that changed while a human was deciding aborts the whole write and a row that started matching in the meantime is not included. A preview that fails is not consent: the invocation falls to its hazard, which holds writes.
Direct web writes from an authenticated organization owner or admin can use inline self-approval: the control plane creates and records the approval under that web identity, then dispatches without a second approval card. Member requests that the policy holds remain pending. Delegated code with hazard unknown always remains pending for separate review.
Approval is not a substitute for least privilege. The action should still use the narrowest downstream credential and validate every input. Approval limits when authority is exercised; IAM limits what that authority can do.

What an approver reviews

An approval is tied to the invocation already recorded by the control plane:
The stable operation name and human-readable title.
The project and environment whose runner would execute the operation.
The schema-validated input for this invocation.
The caller attribution carried from Slack, MCP, the web app, or another configured interface.
Approve or deny, plus the decision time and approver attribution available from the configured approval channel.
The available approvers and approval channels are defined during the assisted integration. We validate both successful and denied paths before production handoff.

Pending approval lifecycle

Slack, MCP, and member-initiated web invocations that the policy holds, along with unknown delegated workloads, follow this pending path:
1

Create the request

The caller submits a typed action. The control plane validates its routing context and sees that the policy holds it for approval.
2

Persist pending state

The control plane creates an approval request linked to the original ask and capability invocation. It does not dispatch the work yet.
3

Notify a human

Polycore presents the operation, target, and arguments in the configured approval surface, such as Slack or the web dashboard.
4

Apply one decision

The approval store accepts one transition out of pending state. A repeated or conflicting decision cannot release the same request twice.
5

Dispatch or close

Approval releases the recorded invocation to the selected runner. Denial closes it without downstream execution.
6

Record the outcome

Success, failure, or denial remains linked to the requester, approver, project, environment, capability, and timing.

Audit model

Polycore records two useful levels of activity.

Request

One user-facing ask, including its caller, interface, input, overall outcome, and final answer. A request may involve more than one governed operation.

Capability invocation

One dispatch attempt under that request, including capability, arguments, project, environment, runner, duration, result, and linked approval when applicable.
A third record stores the approval decision itself. This lets a reviewer move from a human request to every production operation it caused without flattening a multi-step ask into unrelated log lines.

Example: one request, two invocations

What is recorded

Audit records may include:
  • Caller and originating interface.
  • Project, environment, and runner.
  • Capability name. Approval records also carry the gated hazard.
  • Validated arguments.
  • Start time, duration, and outcome.
  • A structured result or failure, capped at approximately 32 KiB of JSON with explicit truncation metadata when the cap is exceeded.
  • Approval status and decision attribution.
  • The final user-facing answer for agent requests.
Inputs and outputs can contain customer data even though credentials stay runner-side. During integration, we identify sensitive fields, keep outputs bounded, and decide where actions should redact or summarize data before it returns.

Interface behavior

A request your policy clears replies in the conversation. A held request produces an approval card and waits. The outcome returns to the same request context.

Validation checklist

Before a policy-gated capability is considered ready, we verify:
The runner executes no policy-gated dispatch without an approval decision recorded for that invocation.
Denial leaves the downstream system unchanged and remains visible in audit.
Repeated decisions do not execute the invocation twice.
Downstream failures are recorded and shown to the requester without being reported as success.
Caller, target environment, arguments, and approver context are reviewable together.