This walks through the same flow as the top-level Quickstart,
with more explanation at each step and a focus on the SDK’s own ergonomics. If
you just want the fastest path to a working local server, use
Quickstart instead. This page assumes you’re already inside a
local clone of the Parmana repo with a server you can point at.
Prerequisites
- Python 3.10 or later (
python --version) - Node.js (to run the Parmana server locally,
node --version) - A local clone of the Parmana repo, set up as in Quickstart:
.envcopied from.env.example,npm ciandnpm run buildrun, and thedefaultandgatewaykeys generated
No AI agent action is authorized without a signed human approval, reads
included (Human approval). In this walkthrough you
also play the approver: you make an approver key, the local server trusts it,
and you sign an approval before the agent’s request.
1
Make a local approver key
From the repo root:
2
Start the Runtime locally
From the repo root, override storage to run with no external dependency, and trust the
approver key (honored only with Confirm it’s up:With
NODE_ENV=test):NODE_ENV=test, a generic, credential-free test connector (test-fixture) registers
automatically, no external credentials needed for this walkthrough. See Quickstart
for what each flag does and how to generate a local Gateway keypair if you haven’t already.3
Install the SDK
requests.Session()).4
Connect the client
PARMANA_API_KEYS in the previous step holds one demo caller key for local development only:
callerId: "demo", raw key my-secret-api-key, allowed to use test:fixture-execute and to
act as demo. Its raw key is public: never use it on a server anyone else can reach. api_key is optional only against a server
started with PARMANA_AUTH_DISABLED=true. Every real deployment requires one, and an
omitted/wrong key raises AuthenticationError, not a silent failure.5
Sign the approval
The approver’s step, on the approver’s machine. It approves this action, this target, up to
this amount, for 15 minutes, once:
parmana.crypto needs pip install "parmana[verify]".6
Build a Business Transaction
create_business_transaction() derives every id pair the server checks for internal consistency
(see why that matters), so
there’s nothing to hand-assemble and get wrong:test:fixture-execute is a generic, credential-free capability built for exactly this kind of
walkthrough. It’s unrelated to any real connector, and only registers when the server runs with
NODE_ENV=test.7
Execute it
One call runs the policy decision and, if approved, the connector. There’s no separate
“authorize” step:If the policy denies the transaction,
execute() raises ExecutionRejectedError with the
policy’s own reason in the message. It never returns a “REJECTED” status you’d have to check for.8
Read the proof
trust_record is a real, signed ExecutionTrustRecord:Full script
python/examples/quickstart/run.py;
python/tests/test_quickstart_example.py runs it against a real, freshly-spawned server on every
test run, so it’s verified to work, not just syntax-checked.
Troubleshooting
NetworkError (connection refused) on localhost:3000
The server isn’t running, or isn’t listening on the port you’re pointing at. Confirm with
curl http://localhost:3000/health.
ExecutionRejectedError naming humanApproved
The approval is missing, expired, already used, for another target, below the amount, or signed
by a key the server does not trust. Sign a fresh one, and check the server was started with
PARMANA_TEST_APPROVER_PUBLIC_KEY_FILE pointing at the matching public key.
AuthenticationError (401)
Either no api_key was passed against a server that requires one, or the key is wrong. Confirm
the demo key matches what’s in the repo’s committed .env, or that PARMANA_AUTH_DISABLED=true
is actually set if you intended to skip auth.
ExecutionRejectedError
The named policy denied the transaction. The exception message is the policy’s own reason. Check
that every signal the policy references is present in signals, and that any boundSignals
field (like vendorId above) exactly matches its bound intent field.
ValidationError (400), often “X must equal Y”
A hand-built transaction had two of the three cross-checked id pairs out of sync. Use
create_business_transaction() instead of constructing the object by hand. It makes this class
of mistake one that cannot arise through it.
Next
Python SDK Overview
The concepts behind what you just ran: transactions, decisions, proofs.
Python SDK for AI Agents
Wire this into LangChain, CrewAI, FastAPI, and async agent code.
Python SDK Production
Error handling, audit logging, and a deployment checklist.
End-to-end: agent → Parmana → Paytm
The same flow against a real connector and real infrastructure, not the
local test fixture.