@polycore/runner).
Action boundary
The caller supplies
Schema-valid input through Slack, MCP, a dashboard, or another configured
interface.
The runner supplies
The action’s declared local secrets and a structured logger. Secret values
do not enter the input schema.
Directory-derived identity
Actions are discovered recursively:actions
billing
set-plan
action.ts
id field
to the definition.
Complete example
actions/billing/set-plan/action.ts
Definition fields
string
required
Human-readable operation name used in catalog and approval surfaces.
string
required
Tell an agent when to use the action, what it changes, and important
preconditions. Keep it customer-specific only in the customer’s integration
repository.
string[]
Optional organization metadata for the catalog.
"read" | "write"
default:"\"write\""
What the action is capable of. With no
policy it is the whole decision:
reads dispatch and writes wait for a human. The default is write, so an
omitted classification fails safe.Zod schema
required
Defines and validates all caller-controlled arguments before execution.
Zod schema
required
Defines the structured result advertised to callers. The action implementation
must validate untrusted downstream data against it before returning, as the
example does with
output.parse(data).record<string, string>
Maps every local secret key the action needs to a human-readable description.
function
required
Receives
{ input, secrets, log } and returns the declared output, either
directly or as a promise.function
Decides whether this invocation dispatches, waits for an admin, or is refused,
overriding the hazard default. Receives It must be a pure function of its context: no I/O, no clock, no counters.
{ input, environment, via } and
returns { decision: "allow" }, { decision: "admin_approval", because }, or
{ decision: "never", because }.because reaches the approver and the audit record. See approvals and
audit.Import rules
ImportdefineAction, z, and action types from the runner SDK:
@polycore/ui.
Hazard selection
- read
- write
Use only for side-effect-free operations: the implementation and credential
must not mutate state. Marking an action
read states that the operation
carries no side effects.write.
Secret resolution
An action declares names, not values:- Confirms that each declared key has a local value.
- Builds the
secretsobject for that action. - Executes on the runner host.
- Never adds the values to capability metadata or the caller’s input.
Input design
Good action inputs are narrow, explicit, and reviewable.Prefer stable identifiers
Accept
accountId rather than an unbounded search phrase when the action
targets one account.Encode limits
Use enums, numeric bounds, URL validation, and discriminated unions so
invalid authority cannot be requested.
Avoid secret arguments
Secrets belong in the action declaration and runner environment, not in
caller input.
Keep approval legible
An approver should be able to understand the requested change from the
action title and validated input.
Output design
Return enough information to confirm the effect without leaking the downstream credential or a large raw response. Recommended output fields include:- The stable id of the affected resource.
- The previous and current state relevant to the operation.
- A downstream operation id when it is safe and useful.
- An explicit status for no-op or already-complete behavior.
Failure behavior
Throw an error when the action cannot establish the declared result. Do not convert permission failures, timeouts, validation errors, or downstream rejections into successful-looking output. Use the logger for concise progress:log.infofor meaningful start or stage information.log.warnfor recoverable conditions the caller should know.log.errorbefore a failure only when it adds context.log.successfor a completed effect.
Review checklist
The action imports only from the runner SDK (
@polycore/runner) for its
Polycore and Zod API.The folder path provides the intended catalog id and the definition has no
id field.Input and output schemas are narrow, and the hazard matches every side effect.
Declared secrets are the minimum authority required and are not logged or
returned.
Downstream failures remain failures and outputs are bounded.
Tests cover success, validation, authorization failure, and relevant no-op or
idempotency behavior before deployment.

