Approve sensitive agent actions
Pause before a sensitive action, let a person review the request, then continue from its saved checkpoint. Choose local review for a development rehearsal or authenticated portal review when reviewer identity and permissions matter.
Before you begin
Published 0.2.0 has a known tool-source binding edge case: if a same-named Python
package and .py module coexist, it can fingerprint the shadowed file while
execution imports the package. Package changes may then leave a pending approval
valid. The correction passes source regressions and awaits the next core release.
Use the supplied file-entrypoint refund example for the documented rehearsal;
its unchanged public OpenAI $250 local approval path has passed on 0.2.0.
Explicit ./refund_tools.py:function references avoid this particular module
resolution defect. Imported helpers remain outside the binding: keep all
reviewed code, business configuration, identity and ledger fixed while paused,
and start a fresh run after changing them. Do not rely on 0.2.0 to detect the
package-shadowing change.
Use Actspan 0.2.0 and a workspace with an approval checkpoint, such as the refund workflow. Keep its saved state and original workspace available. For central review, first connect the portal and use an account authorized to review requests in that workspace.
| Path | Where execution pauses | Who supplies the decision |
|---|---|---|
| Native workflow, local | An explicit kind: approval node |
The local CLI caller; --actor is an audit label |
| Native workflow, central | The same node, reported to Cloud | An authenticated, authorized portal reviewer |
| LangChain tool review | Middleware before a configured tool | An authenticated reviewer through the tool-approval flow |
An approval node protects the steps after it. Put it before the write, and verify that no alternate branch can perform that write first. A prompt asking the model to seek permission does not create an execution checkpoint.
Rehearse a local approval
First complete the fresh sandbox setup,
including customer identity, ledger and ACTSPAN_PORTAL_DISABLED exports. Run
the example's reviewed case, then retain result.output.thread_id:
actspan run workspace.yaml refund_request --no-portal --no-cache --format json \
--input-text 'Claim CLM-1002 on order ORD-1002. My $400 headphones arrived damaged and I uploaded photos. I want a $250 refund.'
Expected result: pending_approval, a saved quote and no payment for CLM-1002.
Earlier payments for other claims remain. From the same workspace directory,
choose one decision:
actspan continue --thread-id "THREAD_ID" --approve \
--actor demo-reviewer --note 'Reviewed the synthetic damage claim.' --format json
Use --reject instead of --approve to test rejection in a separate fresh run.
Inspect the sandbox ledger after either decision. Local actor labels do not
authenticate a person or grant Cloud reviewer permissions.
Use an authenticated portal decision
When switching from the local rehearsal, clear its shell opt-out:
unset ACTSPAN_PORTAL_DISABLED
Also remove any ACTSPAN_PORTAL_DISABLED=1 setting in the workspace's loaded
environment file. Start a fresh run with portal reporting enabled and
--require-portal, without --no-portal. Open its paused run in the portal, review the supplied context,
and record Approve or Reject with an authorized human account. A developer
service credential alone does not acquire reviewer authority.
Continue from the originating workspace:
actspan continue --thread-id "THREAD_ID" --portal-decision --format json
The native OpenAI and Claude refund workflows were qualified on core 0.1.2 with a real local Cloud browser session: pause with no payment, human approval, refusal after configuration drift, then one reviewed payment after restoring the reviewed configuration. This is historical qualification, not a repeat of the complete browser path on 0.2.0. Production OIDC and a portal-launched runner need their own setup.
Handle a changed configuration
Actspan binds a native pending approval to the effective workspace, policy,
declared local Python entrypoints, provider lock and relevant nonsecret runtime
configuration. Changing a reviewed agent's tools or other bound behavior returns
APPROVAL_CONFIGURATION_CHANGED before continuation or central claim consumption.
Start a new run and request a new review for the changed configuration.
Old pending state without this binding returns APPROVAL_CONFIGURATION_UNBOUND;
create a fresh request rather than editing the saved state. Comments, YAML map
ordering and rotating a credential value do not themselves change this binding.
Restoring the original effective configuration can allow its still-pending
decision to continue. Supply no replacement input or variable overrides with an
approval decision; approve the saved request or create a new one.
This integrity check does not fingerprint every imported helper, installed dependency, remote service or business record. It is not a signature protecting state from someone able to rewrite local files. Verify the actual tool result and business receipt after a resumed write.
Source-only: declare local implementation dependencies
The current source adds explicit runtime.source_files for native Python tools.
This is not included in published 0.2.0; use it only with a source build or
later release that has been qualified for this field. Keep the public refund
workspace unchanged when following the 0.2.0 walkthrough.
runtime:
kind: python_function
entrypoint: ./refund_tools.py:issue_reviewed_refund
source_files:
- refund_service.py
- refund_policy.yaml
- data/fixtures.json
The list names the local code and static configuration you intend to review,
relative to the resolved entrypoint's directory. Actspan binds their exact bytes
and rechecks them before continuation and central approval claim. An edit to a
declared helper invalidates the earlier configuration; a missing or unreadable
dependency fails closed. A changed list also changes the reviewed identity.
Equivalent ordering, duplicate names and ./ spelling normalize consistently.
Use explicit regular files, not glob patterns, directories, symlinks, absolute paths, parent traversal or environment expressions. Include every relevant local helper/configuration file deliberately; the runtime does not discover imports. Do not list a mutable payment ledger as implementation code. Installed packages, undeclared dependencies, remote systems and business records still need their own artifact/data controls. This is a bounded local integrity check, not an immutable filesystem snapshot or remote attestation.
Approve a LangChain tool
Use the LangChain integration
with tools.approval_required, the supplied middleware and durable checkpointer.
The review binds the particular tool, arguments and saved request state; a plain
callback wrapper cannot add this continuation to an arbitrary graph. Grants are
consumed before dispatch. A crash between consumption and the business commit
requires inspecting the business system before arranging another request.
Acceptance before relying on a new deployment
The existing public 0.2.0 workaround is a fixed-file rehearsal. Before claiming changed-implementation rejection on a replacement, retain its exact archive hash/build and show unchanged continuation, same-named package/module changes, changed declared helper/static-policy dependencies and missing dependencies. Establish refusal before tool dispatch or central decision consumption and no new payment. Undeclared imports and remote implementations remain outside that scope.
Authenticated approval also needs a current delivered core/portal tuple. Repeat approve, reject, unauthorized-reviewer denial, configuration change, restart/resume and duplicate-attempt checks with independent ledger inspection. The historical core 0.1.2 recording does not satisfy that gate for 0.2.0, a source patch or a production OIDC deployment. These are required qualification scenarios, not results newly obtained by this documentation change.