Skip to main content

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 approved ExecutionTrustRecord.
The four patterns below wire that call into the shapes a Node.js AI stack actually uses: a LangChain.js tool, a Vercel AI SDK tool, a plain server endpoint, and an async/webhook workflow. Each assumes the client and createBusinessTransaction setup from the quickstart.

Pattern 1: LangChain.js tool

The tool’s return value is a string the agent reads — a denial reads as a normal tool result, not a thrown exception the agent has to recover from mid-conversation.

Pattern 2: Vercel AI SDK tool calling

Returning a structured { 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:
A Fastify route handler follows the same shape — swap 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 on await:
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 with client.verify() regardless of which pattern above produced it.
  • signals are checked against boundSignals before policy evaluation, so an agent can’t satisfy the policy’s signals while pointing target/parameters somewhere 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.