Skip to main content
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.
Want a server to call first? Run one locally with the Quickstart, then point the SDK at it: ParmanaClient(endpoint="http://localhost:3000", api_key="<your-api-key>").

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: .env copied from .env.example, npm ci and npm run build run, and the default and gateway keys 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 NODE_ENV=test):
Confirm it’s up:
With 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

Real PyPI package. See Python SDK for the current published version and what’s inside it (generated models, a typed error taxonomy, a real bearer-key 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:
This same call, run for real against a local server, is captured verbatim in Quickstart’s “Real output” step. Expect the same shape (a fresh hash each run, since the transaction and timestamp differ). See Execution Trust Records for the complete field-by-field shape, and Verify independently to check the signature yourself instead of trusting this output.

Full script

The same, already-tested version of this script lives at 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.