Paidwen

The SDK connects your agent to Paidwen.

The SDK asks Paidwen before each action of your agent, then applies the answer. Your agent keeps its own tool keys and performs each action itself. Your coding assistant can connect the agent from one prompt, or you connect it manually.

1. You copy the key of your agent.

When you sign up, Paidwen asks for the name of your first agent, then shows its key once. You declare any other agent on the Agents screen of the dashboard. Keep the key for step 3.

2. You paste this prompt into your coding assistant.

Paste the prompt into Claude Code, Cursor or another coding assistant, opened in the project of your agent. The assistant installs the SDK, prepares the environment file, creates the client, makes each action of the agent ask Paidwen first, and sends the model calls to the journal. Review its changes as you review any change to your code.

Prompt
Add Paidwen to this project. Paidwen checks each action of an AI agent before it runs.
Read https://paidwen.com/llms-full.txt first: it holds the whole documentation.

1. Find the language of the agent: TypeScript (Node.js 22 or later) or Python (3.10 or later). Install only that SDK: npm install paidwen, or pip install paidwen. Pin its version the way the project pins its other dependencies.
2. The SDK reads the key of the agent from the PAIDWEN_API_KEY environment variable. Never write the key in the code. If the project has an environment file, add the line PAIDWEN_API_KEY= to it without a value, and to its example file if there is one. Otherwise, create .env with this line, and .env.example with the same line. Make sure that git ignores the file that will hold the key.
3. Make the agent load this file when it starts, the way the project loads its other settings. If the project has no such way, add --env-file-if-exists=.env to the node command that starts the agent (Node.js 22.9 or later), or, in Python, install python-dotenv and call load_dotenv() before the client is created.
4. Create one Paidwen client where the agent starts. It throws PaidwenError while the key is missing.
5. Wrap each tool function of the agent with paidwen.tool and a clear tool name, such as payments.refund, even when the function makes HTTP calls itself. In TypeScript, the wrapped function takes one object, whose keys become the parameters that Paidwen reads. Use paidwen.http() only for HTTP calls that go through no tool function. If the agent uses the official MCP SDK, call paidwen.mcp on its client class.
6. Never put a secret, such as a key or a password, in the parameters of a wrapped function: Paidwen receives them as they are.
7. Where the agent calls its tools, catch DeniedError. When a model chose the tool, give it the message of DeniedError as the tool result, so that it knows the action was refused. Let the other errors of Paidwen stop the agent.
8. If the agent calls a model, send its model calls to the journal, so that Paidwen counts their cost in the budget. Follow the quickstart step "Your agent sends its model calls to the journal", and the configuration page for Anthropic and the Vercel AI SDK. Use only the packages that the configuration page lists as working, and tell me if none covers how the agent calls its model. If the project already has an OpenTelemetry tracer provider, add the Paidwen span processor to it instead of creating a second one.
9. Before the process exits, await paidwen.shutdown() in TypeScript, or call paidwen.close() in Python, so that the journal receives the last actions and model calls.
10. At the end, tell me in which file to paste the key of the agent, and list each tool name with the names of its parameters, so that I can write Paidwen rules on them.

3. You paste the key in the environment file.

The assistant tells you which file holds the line PAIDWEN_API_KEY=, usually .env at the root of the project. Paste the key after the equal sign. Git ignores this file, so the key stays on your machine. In production, set PAIDWEN_API_KEY in the environment of the agent instead.

When the agent runs, its actions appear on the Actions screen of the dashboard, and the cost of its model calls on the Costs screen.

1. You copy the key of your agent.

When you sign up, Paidwen asks for the name of your first agent, then shows its key once. You declare any other agent on the Agents screen of the dashboard.

2. You install the SDK of your agent's language.

npm install paidwen
pip install paidwen

The TypeScript SDK runs on Node.js 22 or later, and the Python SDK on Python 3.10 or later. Both are open source under the Apache 2.0 license.

3. You put the key in an environment file.

The SDK reads the key from the PAIDWEN_API_KEY environment variable, so the key never enters the code. In a project without an environment file, create .env at the root of the project with this line, then paste the key after the equal sign:

.env
PAIDWEN_API_KEY=

Add .env to .gitignore, so that the key never reaches git. Write the same line without the key in .env.example, so that the next developer knows the variable.

The agent loads .env when it starts. A project that already loads its environment file keeps its method. Otherwise, Node.js 22.9 or later loads it with the flag below. In Python, pip install python-dotenv installs python-dotenv, and load_dotenv() loads the file before the agent creates its client:

node --env-file-if-exists=.env agent.js
from dotenv import load_dotenv

load_dotenv()

In production, set PAIDWEN_API_KEY in the environment of the agent. A variable set in the environment wins over the file.

4. Your agent creates one client when it starts.

import { Paidwen } from "paidwen";

const paidwen = new Paidwen();
from paidwen import Paidwen

paidwen = Paidwen()

The client reads the key from PAIDWEN_API_KEY, and throws PaidwenError while the key is missing. Every action that goes through the client then asks Paidwen first.

5. Each action reaches Paidwen in one of three ways.

The three ways need no code for any agent framework. An agent built on a framework uses the one that matches how it calls its tools. When the agent runs, its actions appear on the Actions screen of the dashboard.

A wrapped function asks before it runs.

type Refund = { order: string; amount: number };

const refund = paidwen.tool("payments.refund", async (params: Refund) =>
  refundOrder(params.order, params.amount),
);

await refund({ order: "ord_4821", amount: 2500 });
@paidwen.tool("payments.refund")
def refund(order: str, amount: float) -> None:
    refund_order(order, amount)


refund("ord_4821", 2500)

You name the tool. Rules and permissions read the name in tool.name and the arguments in params, here params.order and params.amount. In TypeScript, the wrapped function takes one object, whose keys become params. In Python, the decorator takes the arguments under their names, and an async function works the same way.

The SDK sends the parameters of a wrapped function as they are. Never put a secret, such as a key or a password, in them.

A tool function that makes HTTP calls itself is wrapped too: its name says more than a method and a path.

The HTTP capture asks before each outgoing call.

paidwen.http({ ignore: ["*.internal.example.com"] });
paidwen.http(ignore=["*.internal.example.com"])

Use it for the HTTP calls that go through no wrapped function. Call it when the process starts, before it loads the libraries that make HTTP calls: in an ES module, put the call in its own module and import that module first. Each outgoing call then asks Paidwen before it leaves the process, with its method and its path as tool name, such as POST /v1/refunds. The configuration page lists what the capture sends and the clients it covers.

The MCP capture asks before each tool call.

import { Client } from "@modelcontextprotocol/sdk/client/index.js";

paidwen.mcp(Client);
from mcp import ClientSession

paidwen.mcp(ClientSession)

Each tools/call request of the official MCP SDK asks Paidwen first, with the tool name, its arguments and the name that the server announces. The capture of the class covers every client of the process. A process that runs several agents with their own keys captures one client per agent instead, with paidwen.mcp(client).

6. Your agent sends its model calls to the journal.

Paidwen prices each model call from its tokens, and the budget of the agent counts this cost. The SDK sends the model calls that an OpenTelemetry instrumentation describes, once the tracer provider of the process holds the span processor of the SDK. For the official SDK of OpenAI, install the instrumentation of OpenLLMetry:

npm install @opentelemetry/sdk-trace-node @opentelemetry/instrumentation @traceloop/instrumentation-openai
pip install opentelemetry-sdk opentelemetry-instrumentation-openai

Then register the tracer provider and the instrumentation after the client:

import { registerInstrumentations } from "@opentelemetry/instrumentation";
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
import { OpenAIInstrumentation } from "@traceloop/instrumentation-openai";
import OpenAI from "openai";

new NodeTracerProvider({ spanProcessors: [paidwen.spanProcessor()] }).register();
const openai = new OpenAIInstrumentation();
registerInstrumentations({ instrumentations: [openai] });
openai.manuallyInstrument(OpenAI);
from opentelemetry import trace
from opentelemetry.instrumentation.openai import OpenAIInstrumentor
from opentelemetry.sdk.trace import TracerProvider

provider = TracerProvider()
provider.add_span_processor(paidwen.span_processor())
trace.set_tracer_provider(provider)
OpenAIInstrumentor().instrument()

These lines also cover the OpenAI Agents SDK, which calls the OpenAI SDK. A process that already has a tracer provider adds the span processor to it instead. The configuration page gives the lines for Anthropic and the Vercel AI SDK, and the limits of each package.

7. Your agent closes the client before it exits.

await paidwen.shutdown();
paidwen.close()

The call sends the last actions and model calls to the journal.

The agent applies the answer.

  • allow: the action runs.
  • block or quarantine: the call throws DeniedError, and the action never runs.
  • require_approval or escalate: the call waits for a person, then runs or throws DeniedError. The approvals page shows how the agent waits or hands back control.
import { DeniedError } from "paidwen";

try {
  await refund({ order: "ord_4821", amount: 2500 });
} catch (error) {
  if (!(error instanceof DeniedError)) throw error;
  console.warn(error.message);
}
from paidwen import DeniedError

try:
    refund("ord_4821", 2500)
except DeniedError as error:
    print(error)

The message of DeniedError says when the agent's permissions or budget refused the action, and error.decision carries the whole decision.

The configuration page holds the options and the limits.

The SDK needs no other setting. When Paidwen does not answer within 3 seconds, the SDK blocks the action by default. The configuration page lists the options of the client, the rules of the HTTP capture, the packages tested for the model calls, and what the SDK does not see.