@zuora/agent-toolkit 0.0.1-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +298 -0
- package/dist/async-jobs-Dd8Jafv0.d.ts +532 -0
- package/dist/bundle-catalog-3V6EICKE.json +289 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +496 -0
- package/dist/index.js.map +1 -0
- package/dist/langchain/index.d.ts +2 -0
- package/dist/langchain/index.js +1 -0
- package/dist/langchain/index.js.map +1 -0
- package/dist/mcp/index.d.ts +2 -0
- package/dist/mcp/index.js +1 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/openai/index.d.ts +165 -0
- package/dist/openai/index.js +5257 -0
- package/dist/openai/index.js.map +1 -0
- package/dist/openai-agents/index.d.ts +94 -0
- package/dist/openai-agents/index.js +5203 -0
- package/dist/openai-agents/index.js.map +1 -0
- package/dist/shared/resources/bundle-catalog.json +289 -0
- package/dist/shared/toolkit-core.d.ts +73 -0
- package/dist/shared/toolkit-core.js +4686 -0
- package/dist/shared/toolkit-core.js.map +1 -0
- package/dist/toolkit-CafRZuAV.d.ts +31 -0
- package/dist/vercel-ai/index.d.ts +2 -0
- package/dist/vercel-ai/index.js +1 -0
- package/dist/vercel-ai/index.js.map +1 -0
- package/package.json +95 -0
package/README.md
ADDED
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
# @zuora/agent-toolkit
|
|
2
|
+
|
|
3
|
+
> **Alpha release** — APIs may change before the 1.0 stable release.
|
|
4
|
+
|
|
5
|
+
Zuora billing operations as callable tools for AI agent frameworks.
|
|
6
|
+
|
|
7
|
+
Built on the [Zuora MCP server](https://developer.zuora.com). Tool inventory is discovered at runtime from your tenant's MCP endpoint — it is not hardcoded in this package.
|
|
8
|
+
|
|
9
|
+
## Adapter status
|
|
10
|
+
|
|
11
|
+
| Subpath | Factory | Status |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| `@zuora/agent-toolkit/openai` | `createZuoraOpenAIAgentToolkit` | ✅ Implemented |
|
|
14
|
+
| `@zuora/agent-toolkit/openai-agents` | `createZuoraOpenAIAgentsToolkit` | ✅ Implemented |
|
|
15
|
+
| `@zuora/agent-toolkit/langchain` | — | 🚧 Coming soon |
|
|
16
|
+
| `@zuora/agent-toolkit/vercel-ai` | — | 🚧 Coming soon |
|
|
17
|
+
| `@zuora/agent-toolkit/mcp` | — | 🚧 Coming soon |
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @zuora/agent-toolkit
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Framework packages are peer dependencies — install only what you use:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# OpenAI Chat Completions
|
|
29
|
+
npm install openai
|
|
30
|
+
|
|
31
|
+
# OpenAI Agents SDK
|
|
32
|
+
npm install @openai/agents
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Credentials
|
|
36
|
+
|
|
37
|
+
The toolkit authenticates against Zuora using OAuth 2.0 client credentials. You need:
|
|
38
|
+
|
|
39
|
+
- `ZUORA_BASE_URL` — your Zuora tenant REST API base URL (e.g. `https://rest.apisandbox.zuora.com`)
|
|
40
|
+
- `ZUORA_CLIENT_ID` — OAuth client ID
|
|
41
|
+
- `ZUORA_CLIENT_SECRET` — OAuth client secret
|
|
42
|
+
|
|
43
|
+
**Use a client scoped to the minimum permissions your agent needs.** Never use admin credentials.
|
|
44
|
+
|
|
45
|
+
## Usage
|
|
46
|
+
|
|
47
|
+
### OpenAI Agents SDK
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
import { Agent, run } from "@openai/agents";
|
|
51
|
+
import { createZuoraOpenAIAgentsToolkit } from "@zuora/agent-toolkit/openai-agents";
|
|
52
|
+
|
|
53
|
+
const toolkit = await createZuoraOpenAIAgentsToolkit({
|
|
54
|
+
env: true,
|
|
55
|
+
configuration: { mode: "readOnly", bundles: { query: true } },
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const tools = await toolkit.getTools({ bundles: ["query"] });
|
|
59
|
+
const agent = new Agent({ name: "Billing Agent", tools });
|
|
60
|
+
const result = await run(agent, "How many active billing accounts do we have?");
|
|
61
|
+
|
|
62
|
+
await toolkit.close();
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
If you already have a Chat Completions toolkit, you can bridge it with `buildAgentsTools`:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import { buildAgentsTools } from "@zuora/agent-toolkit/openai-agents";
|
|
69
|
+
import { createZuoraOpenAIAgentToolkit } from "@zuora/agent-toolkit/openai";
|
|
70
|
+
import { tool } from "@openai/agents";
|
|
71
|
+
|
|
72
|
+
const chatToolkit = await createZuoraOpenAIAgentToolkit({ env: true });
|
|
73
|
+
const tools = await buildAgentsTools(tool, chatToolkit, { bundles: ["query"] });
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### OpenAI Chat Completions
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import OpenAI from "openai";
|
|
80
|
+
import {
|
|
81
|
+
createZuoraOpenAIAgentToolkit,
|
|
82
|
+
handleToolCalls,
|
|
83
|
+
} from "@zuora/agent-toolkit/openai";
|
|
84
|
+
|
|
85
|
+
const toolkit = await createZuoraOpenAIAgentToolkit({
|
|
86
|
+
env: true,
|
|
87
|
+
configuration: { mode: "readOnly" },
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const client = new OpenAI();
|
|
91
|
+
const tools = await toolkit.getTools({ bundles: ["accounts", "query"] });
|
|
92
|
+
const messages: OpenAI.ChatCompletionMessageParam[] = [
|
|
93
|
+
{ role: "user", content: "List 3 active accounts" },
|
|
94
|
+
];
|
|
95
|
+
|
|
96
|
+
for (let step = 0; step < 20; step++) {
|
|
97
|
+
const response = await client.chat.completions.create({
|
|
98
|
+
model: "gpt-4o",
|
|
99
|
+
messages,
|
|
100
|
+
tools,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const choice = response.choices[0];
|
|
104
|
+
if (!choice) break;
|
|
105
|
+
messages.push(choice.message);
|
|
106
|
+
|
|
107
|
+
if (choice.finish_reason === "tool_calls") {
|
|
108
|
+
const { messages: toolMessages } = await handleToolCalls({ toolkit, response });
|
|
109
|
+
messages.push(...toolMessages);
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
console.log(choice.message.content);
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
await toolkit.close();
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Configuration
|
|
121
|
+
|
|
122
|
+
### Safety modes
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
configuration: {
|
|
126
|
+
mode: "readOnly", // only read operations (default)
|
|
127
|
+
// or
|
|
128
|
+
mode: "writeEnabled", // read + write operations
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Tool bundles
|
|
133
|
+
|
|
134
|
+
Select groups of tools by Zuora domain:
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
configuration: {
|
|
138
|
+
bundles: {
|
|
139
|
+
accounts: true,
|
|
140
|
+
subscriptions: true,
|
|
141
|
+
query: true,
|
|
142
|
+
},
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Available bundles: `accounts`, `catalog`, `subscriptions`, `orders`, `billing`, `payments`, `usage`, `revenue`, `finance`, `workflows`, `query`, `admin`, `files`.
|
|
147
|
+
|
|
148
|
+
You can also filter at call time via `getTools({ bundles, include, exclude, mode })`.
|
|
149
|
+
|
|
150
|
+
### Exclude / include specific tools
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
configuration: {
|
|
154
|
+
bundles: {
|
|
155
|
+
billing: {
|
|
156
|
+
exclude: ["create_invoice", "delete_invoice"],
|
|
157
|
+
// or include: ["list_invoices"]
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Split operations
|
|
164
|
+
|
|
165
|
+
Multi-operation MCP tools are split into per-operation tools by default (`splitOperations: true`), producing names like `manage_data_queries__submit_query`. Set `splitOperations: false` to keep merged tools.
|
|
166
|
+
|
|
167
|
+
### Approval policy
|
|
168
|
+
|
|
169
|
+
Gate write / high-risk operations before they reach Zuora. `approvalPolicy` is a **top-level** config field (not inside `configuration`):
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
import { ApprovalPolicyPreset } from "@zuora/agent-toolkit";
|
|
173
|
+
|
|
174
|
+
const toolkit = await createZuoraOpenAIAgentToolkit({
|
|
175
|
+
env: true,
|
|
176
|
+
configuration: { mode: "writeEnabled" },
|
|
177
|
+
approvalPolicy: ApprovalPolicyPreset.HighRisk,
|
|
178
|
+
// or a custom handler:
|
|
179
|
+
// approvalPolicy: async (request) => {
|
|
180
|
+
// if (request.tool.meta.riskLevel === "high") return "deny";
|
|
181
|
+
// return "not_required";
|
|
182
|
+
// },
|
|
183
|
+
});
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Presets: `Off`, `AllWrites`, `HighRisk`, `ProductionWrites`, `ProductionHighRisk`.
|
|
187
|
+
|
|
188
|
+
### Context defaults
|
|
189
|
+
|
|
190
|
+
Pass optional string context keys (for example tenant or entity identifiers) via `configuration.context`. Connection-level `entityIds` / `orgIds` arrays live on `connection` instead:
|
|
191
|
+
|
|
192
|
+
```ts
|
|
193
|
+
configuration: {
|
|
194
|
+
context: {
|
|
195
|
+
tenantId: "…",
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
connection: {
|
|
199
|
+
entityIds: ["entity-1"],
|
|
200
|
+
orgIds: ["org-1"],
|
|
201
|
+
},
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Observability
|
|
205
|
+
|
|
206
|
+
```ts
|
|
207
|
+
observability: {
|
|
208
|
+
onEvent: (event) => { /* tool.called, tool.completed, approval.*, … */ },
|
|
209
|
+
logger: { info: console.info, warn: console.warn, error: console.error },
|
|
210
|
+
includePayloads: false, // default; set true to include sanitized I/O
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Environment variable config
|
|
215
|
+
|
|
216
|
+
Pass `env: true` to read credentials from the environment automatically:
|
|
217
|
+
|
|
218
|
+
```ts
|
|
219
|
+
const toolkit = await createZuoraOpenAIAgentToolkit({
|
|
220
|
+
env: true,
|
|
221
|
+
configuration: { mode: "readOnly" },
|
|
222
|
+
});
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
| Variable | Purpose |
|
|
226
|
+
|---|---|
|
|
227
|
+
| `ZUORA_BASE_URL` or `ZUORA_MCP_URL` | Endpoint (required) |
|
|
228
|
+
| `ZUORA_CLIENT_ID` / `ZUORA_CLIENT_SECRET` | OAuth credentials |
|
|
229
|
+
| `ZUORA_TOOLKIT_MODE` | `readOnly` (default) or `writeEnabled` |
|
|
230
|
+
|
|
231
|
+
You can still pass `baseUrl` + `auth` explicitly instead of `env: true`.
|
|
232
|
+
|
|
233
|
+
## Lifecycle
|
|
234
|
+
|
|
235
|
+
Always call `close()` when done:
|
|
236
|
+
|
|
237
|
+
```ts
|
|
238
|
+
const toolkit = await createZuoraOpenAIAgentToolkit({ env: true });
|
|
239
|
+
try {
|
|
240
|
+
// use toolkit
|
|
241
|
+
} finally {
|
|
242
|
+
await toolkit.close();
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## Discovery and execution
|
|
247
|
+
|
|
248
|
+
```ts
|
|
249
|
+
const tools = await toolkit.listTools(); // ZuoraToolDefinition[]
|
|
250
|
+
const def = await toolkit.describeTool("get_account");
|
|
251
|
+
const bundles = await toolkit.listBundles();
|
|
252
|
+
const bundle = await toolkit.describeBundle("subscriptions");
|
|
253
|
+
|
|
254
|
+
const result = await toolkit.callTool("get_account", { accountKey: "…" });
|
|
255
|
+
// For async tools: await toolkit.waitForJob(toolName, asyncResult, options?)
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## Native query / file tools
|
|
259
|
+
|
|
260
|
+
When the `query` bundle is enabled, the SDK may expose local helpers such as `download_query_result` and `read_downloaded_file` so agents can fetch and preview Data Query artifacts. Artifacts default to `~/.zuora-agent-artifacts`.
|
|
261
|
+
|
|
262
|
+
## Errors
|
|
263
|
+
|
|
264
|
+
All SDK errors are `ZuoraAgentToolkitError` with a typed `code`:
|
|
265
|
+
|
|
266
|
+
| Code | Meaning |
|
|
267
|
+
|---|---|
|
|
268
|
+
| `OAUTH_TOKEN_ERROR` | Authentication or token refresh failed |
|
|
269
|
+
| `TOOL_EXECUTION_ERROR` | MCP tool call failed |
|
|
270
|
+
| `TOOL_NOT_FOUND` | Unknown tool name |
|
|
271
|
+
| `BUNDLE_NOT_FOUND` | Unknown bundle name |
|
|
272
|
+
| `APPROVAL_REJECTED` | Approval policy rejected the operation |
|
|
273
|
+
| `MALFORMED_METADATA` | Server returned incomplete or invalid tool metadata |
|
|
274
|
+
| `ASYNC_JOB_TIMEOUT` | Async job polling timed out |
|
|
275
|
+
|
|
276
|
+
```ts
|
|
277
|
+
import { ZuoraAgentToolkitError } from "@zuora/agent-toolkit";
|
|
278
|
+
|
|
279
|
+
try {
|
|
280
|
+
await handleToolCalls({ toolkit, response });
|
|
281
|
+
} catch (err) {
|
|
282
|
+
if (err instanceof ZuoraAgentToolkitError && err.code === "APPROVAL_REJECTED") {
|
|
283
|
+
// handle rejection
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
## Examples
|
|
289
|
+
|
|
290
|
+
Working examples are available in the source repository:
|
|
291
|
+
|
|
292
|
+
| Example | Description |
|
|
293
|
+
|---|---|
|
|
294
|
+
| `examples/openai/index.ts` | Minimal Chat Completions agent loop |
|
|
295
|
+
| `examples/openai/advanced.ts` | Observability, hooks, async jobs, discovery |
|
|
296
|
+
| `examples/openai/hitl.ts` | Human-in-the-loop via `shouldExecute` |
|
|
297
|
+
| `examples/openai-agents/index.ts` | OpenAI Agents SDK agent |
|
|
298
|
+
| `examples/openai-agents-cli/` | Interactive CLI agent + planner |
|