Catalog PyPI
PACKAGE EXPLORERView in registry

action-marshall

PyPI

Action-level release control for AI agents: preview, approve, canary, halt, and audit tool actions before they touch production.

agent-governanceagentsaiai-agentsapprovalauditcanarycircuit-breakerpolicytool-use
Versions collected1
Direct dependencies14From release 0.1.0
Last observed20 Oct, 18:33 UTC

README

Version 0.1.0 documentation

action-marshall

Action-level release control for AI agents. Preview, approve, canary, halt, and audit tool actions before they touch production.

action-marshall is the Python SDK for Action Marshall. Wrap the tools or functions your agent already calls — Action Marshall runs preview, policy, approval, canary, breaker, and signed audit before the action is released.

Status: 0.1.0 — pre-1.0 alpha. The API may change before 1.0.0.


Install

pip install action-marshall

Python 3.9+.

You also need a backend

action-marshall is the client SDK. It talks to an Action Marshall backend that runs the policy engine, signs receipts, and stores audit history. To try it end-to-end you have two paths:

Option A — local backend via Docker (recommended for evaluation)

git clone https://github.com/SatwikReddySripathi/action-marshall.git
cd action-marshall
docker compose up --build

Backend lives at http://localhost:8000, dashboard at http://localhost:3000. Wait until curl http://localhost:8000/ready returns 200. Default API key is am_test_demo_key_001.

Option B — point at a hosted backend (planned — hosted Action Marshall is not live yet)

Once hosted Action Marshall opens, you'll get an API key and a base_url. Join the waitlist.

Optional framework adapters:

pip install "action-marshall[langchain]"     # available now (experimental)
pip install "action-marshall[langgraph]"     # planned
pip install "action-marshall[crewai]"        # planned
pip install "action-marshall[autogen]"       # planned
pip install "action-marshall[mcp]"           # planned
pip install "action-marshall[llamaindex]"    # planned
pip install "action-marshall[openai]"        # planned
pip install "action-marshall[all]"

Quickstart

Assuming the backend is up at http://localhost:8000:

from action_marshall import MarshallClient, Action, ActionParams

ks = MarshallClient(
    api_key="am_test_demo_key_001",
    base_url="http://localhost:8000",
)

result = ks.run(Action(
    tool="servicenow",
    action_type="bulk_update",
    params=ActionParams(
        connector="servicenow_sim",
        query={"state": "open", "priority": {"op": "in", "value": ["P3", "P4"]}},
        changes={"state": "in_progress"},
    ),
))

print(result.decision_value)   # AUTO | CANARY | BLOCK | APPROVAL_REQUIRED
print(result.status)           # completed | contained | blocked | awaiting_approval | observed
print(result.blast_radius)     # 17
print(result.proof_url)        # /v1/actions/<id>/proof

Open result.ui_urls["detail"] in your browser to see the full action in the dashboard.


Wrap an existing function

The killer pattern — every call becomes a governed action:

@ks.wrap_function(
    tool="servicenow",
    action_type="update_incident",
    connector="servicenow_sim",
    agent_id="incident-triage",
)
def update_incident(payload: dict) -> dict:
    # your existing implementation
    ...

result = update_incident({"incident_id": "INC001", "status": "resolved"})
  • AUTO → the wrapped function runs normally.
  • BLOCK → wrapped function is not called; MarshallDenied is raised.
  • APPROVAL_REQUIRED → wrapped function is not called; MarshallApprovalRequired is raised. Approve in Slack or the web UI, the next call goes through.

Pass on_denied=... / on_approval_required=... callbacks if you want to handle these without exceptions:

@ks.wrap_function(
    tool="servicenow", action_type="update_incident",
    connector="servicenow_sim", agent_id="incident-triage",
    on_denied=lambda err: {"status": "blocked-by-policy", "reasons": err.result.decision.get("reasons")},
)
def update_incident(payload: dict) -> dict: ...

Preview without executing

preview = ks.preview(Action(...))
print(preview.decision_value, preview.blast_radius, preview.preview_hash)

Same lifecycle as run but no writes happen — the policy and canary phases evaluate and a receipt is signed for the dry run.


Wrap a LangChain tool

available now (experimental). Requires pip install "action-marshall[langchain]".

from langchain_core.tools import tool
from action_marshall import MarshallClient
from action_marshall.adapters.langchain import wrap_langchain_tool

@tool
def update_incident(payload: dict) -> dict:
    ...

ks = MarshallClient(api_key="am_...", base_url="http://localhost:8000")

protected = wrap_langchain_tool(
    update_incident, ks=ks,
    tool="servicenow", action_type="update_incident",
    connector="servicenow_sim", agent_id="incident-triage",
)
# protected.invoke({...}) is now governed.

Verify a signed receipt

receipt = ks.verify_receipt("act_abc123")
print(receipt.verified)   # True if the HMAC signature matches
print(receipt.signature)

Server-side verification — the backend re-signs the receipt body and compares with constant-time HMAC. For fully offline verification with a local PROOF_SECRET, see the security docs.


Decisions

DecisionMeaning
AUTOAllowed without approval. The wrapped function runs.
CANARYAllowed, but a canary subset runs first; the breaker can halt.
APPROVAL_REQUIREDHuman approval needed before execution.
BLOCKDisallowed. The wrapped function is not called.

Decision hierarchy: BLOCK > APPROVAL_REQUIRED > CANARY > AUTO. Policies escalate, never de-escalate.

Connectors

ConnectorUse forStatus
servicenow_simSimulated ServiceNow incidents (demo / dev)available now
servicenow_realLive ServiceNow instanceavailable now
email_genericOutbound email actionsavailable now
jira_realLive Jira Cloudplanned

Public API

from action_marshall import (
    MarshallClient,
    Action, ActionParams, Actor, Approval, Approver,
    ActionResult, PreviewResult, Receipt,
    MarshallError, MarshallAPIError, MarshallDenied, MarshallApprovalRequired,
)

The type-checker-friendly py.typed marker ships in the wheel — mypy and pyright will pick up our annotations automatically.


CLI

action-marshall is also installed as a CLI binary. Useful for one-off operations, CI smoke checks, and tools that aren't easily called from Python.

action-marshall --help
action-marshall init                            # write ~/.marshall/config.json
action-marshall preview action.json
action-marshall run action.json
action-marshall receipts list
action-marshall receipts verify act_abc123

Full reference: docs/cli.md.


Local development

git clone https://github.com/SatwikReddySripathi/action-marshall.git
cd action-marshall/sdk
pip install -e ".[dev]"
pytest

License

MIT. See LICENSE.

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 1

Collected releases
VersionPublishedDirect dependenciesOpen version
0.1.026 May 202614

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Repository

PENDING
satwikreddysripathi/action_marshall

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 18:33 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:e12ce57857ddd3aadcb539a04df10ec99f09a86755db176b827e7f07e1aef743