The problem
An AI agent that can call a payment API, a CRM, or a vendor system needs a credential to do it. Give the agent that credential directly and the agent’s own (probabilistic, sometimes wrong) reasoning is the only thing standing between a user’s request and a real-world action.The solution
The agent proposes the action to Parmana as a Business Transaction. A named, versioned policy — not the agent — decides. Your code only calls the downstream system (or, in a real deployment, a registered Connector calls it on Parmana’s behalf) once Parmana returns an approvedExecutionTrustRecord.
client and createBusinessTransaction setup from
the quickstart.
Pattern 1: LangChain.js tool
Pattern 2: Vercel AI SDK tool calling
{ approved, ... } object instead of a string works well here since
the model can reason over the fields directly in a follow-up turn.
Pattern 3: Express / Fastify endpoint
Putting the Parmana call behind your own endpoint keeps the agent’s tool-calling surface thin — the agent calls your API, your API calls Parmana:app.post(path, handler) for
fastify.post(path, async (request, reply) => { ... }) and the body is identical.
Pattern 4: Async workflow with a webhook callback
For an agent whose action needs to run out-of-band (a long-running batch, a human-in-the-loop step) rather than inline in the conversation turn, submit the transaction and notify a webhook when the trust record lands, instead of blocking onawait:
client.execute() itself is a single request/response call, not a streaming one — this
pattern is about decoupling your workflow from the caller’s request/response cycle, not
about Parmana’s own API shape.
Real example: a CustomerServiceAgent class
Key guarantees
- The agent (LangChain.js, the Vercel AI SDK, or a hand-rolled loop) never sees the downstream connector credential — only a registered Connector does.
- A denial surfaces as data (
ExecutionRejectedError, or a{ approved: false }result), not a crash — the calling agent framework’s normal error/retry handling applies. - The policy version is explicit in every call (
policy: { name, version, schemaVersion }) — an agent can’t silently drift onto a different policy between calls. - Every approved execution returns a signed
ExecutionTrustRecord, independently verifiable later withclient.verify()regardless of which pattern above produced it. signalsare checked againstboundSignalsbefore policy evaluation, so an agent can’t satisfy the policy’s signals while pointingtarget/parameterssomewhere else.
Next
TypeScript SDK in Production
Config, retries, audit logging, and a deployment checklist for the pattern
above.
Write your first policy
What
customer-refund@1.0.0 actually evaluates, and how to write your own.Connect an agent
The framework-agnostic version of this page’s four patterns.
End-to-end: agent → Parmana → Paytm
This exact
paytm:refund action, run against real, live infrastructure.