@balchemyai/agent-sdk 0.2.1 → 0.2.5
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/CHANGELOG.md +26 -0
- package/README.md +129 -121
- package/docs/QUICKSTART.md +7 -3
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,32 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [0.2.5] — 2026-05-28
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Align the public SDK and CLI release line with the backend MCP catalog, resource, and prompt hardening shipped after `0.2.4`.
|
|
15
|
+
- Document the stricter observability and telemetry privacy boundary for agent-facing MCP responses.
|
|
16
|
+
- Keep autonomous agent runtime expectations explicit: SDK/CLI clients remain API clients and execution still flows through scoped MCP credentials and server-side safety checks.
|
|
17
|
+
|
|
18
|
+
### Notes
|
|
19
|
+
|
|
20
|
+
- No wallet keys, trading internals, or backend policy logic are shipped in the public packages.
|
|
21
|
+
- Publish `@balchemyai/agent-sdk@0.2.5` before `balchemy@0.2.5` so the CLI dependency resolves from npm semver.
|
|
22
|
+
|
|
23
|
+
## [0.2.4] — 2026-05-24
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- Align SDK public package version with the `balchemy` CLI release line.
|
|
28
|
+
- Refresh public package metadata so npm repository links point to `github.com/balchemy/balchemy-agent`.
|
|
29
|
+
- Keep the SDK release available as the npm-compatible dependency target for `balchemy@0.2.4`.
|
|
30
|
+
|
|
31
|
+
### Notes
|
|
32
|
+
|
|
33
|
+
- Public CLI and SDK releases should stay version-aligned unless a release note explicitly says otherwise.
|
|
34
|
+
- CLI packages must depend on the published SDK with npm semver, not `workspace:` ranges.
|
|
35
|
+
|
|
10
36
|
## [0.1.0] — 2026-03-15
|
|
11
37
|
|
|
12
38
|
### Added
|
package/README.md
CHANGED
|
@@ -1,18 +1,35 @@
|
|
|
1
1
|
# @balchemyai/agent-sdk
|
|
2
2
|
|
|
3
|
-
TypeScript SDK for
|
|
3
|
+
TypeScript SDK for external agents that connect to Balchemy through MCP. Use it
|
|
4
|
+
to onboard an agent, request scoped access, call tools, refresh tokens, and
|
|
5
|
+
consume SSE events.
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
Balchemy does not ask an inner model to make trade decisions. Your outer LLM
|
|
8
|
+
chooses tools. Balchemy checks policy, executes through the authorized path, and
|
|
9
|
+
keeps the record.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
6
12
|
|
|
7
13
|
```sh
|
|
8
14
|
npm install @balchemyai/agent-sdk
|
|
9
15
|
```
|
|
10
16
|
|
|
11
|
-
##
|
|
17
|
+
## Create a Client
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { BalchemyAgentSdk } from "@balchemyai/agent-sdk";
|
|
21
|
+
|
|
22
|
+
const sdk = new BalchemyAgentSdk({
|
|
23
|
+
apiBaseUrl: "https://api.balchemy.ai/api",
|
|
24
|
+
});
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`apiBaseUrl` includes `/api` and has no trailing slash.
|
|
12
28
|
|
|
13
|
-
|
|
29
|
+
## Auth Path 1: SIWE
|
|
14
30
|
|
|
15
|
-
Use this when
|
|
31
|
+
Use this path when the agent controls a wallet and can sign an off-chain
|
|
32
|
+
message.
|
|
16
33
|
|
|
17
34
|
```ts
|
|
18
35
|
import { BalchemyAgentSdk } from "@balchemyai/agent-sdk";
|
|
@@ -21,24 +38,21 @@ const sdk = new BalchemyAgentSdk({
|
|
|
21
38
|
apiBaseUrl: "https://api.balchemy.ai/api",
|
|
22
39
|
});
|
|
23
40
|
|
|
24
|
-
|
|
25
|
-
const { message, nonce } = await sdk.requestSiweNonce({
|
|
41
|
+
const { message } = await sdk.requestSiweNonce({
|
|
26
42
|
address: "YOUR_WALLET_ADDRESS",
|
|
27
43
|
chainId: 8453,
|
|
28
|
-
domain: "
|
|
29
|
-
uri: "https://
|
|
44
|
+
domain: "agent.example.com",
|
|
45
|
+
uri: "https://agent.example.com",
|
|
30
46
|
statement: "Sign in to Balchemy",
|
|
31
47
|
});
|
|
32
48
|
|
|
33
|
-
// 2. Sign `message` with your wallet (off-chain, using your signing library)
|
|
34
49
|
const signature = await wallet.signMessage(message);
|
|
35
50
|
|
|
36
|
-
// 3. Onboard
|
|
37
51
|
const response = await sdk.onboardWithSiwe({
|
|
38
52
|
message,
|
|
39
53
|
signature,
|
|
40
|
-
agentId: "
|
|
41
|
-
scope: "trade",
|
|
54
|
+
agentId: "agent-example",
|
|
55
|
+
scope: "trade",
|
|
42
56
|
});
|
|
43
57
|
|
|
44
58
|
const mcp = sdk.connectMcp({
|
|
@@ -47,9 +61,10 @@ const mcp = sdk.connectMcp({
|
|
|
47
61
|
});
|
|
48
62
|
```
|
|
49
63
|
|
|
50
|
-
|
|
64
|
+
## Auth Path 2: Walletless Identity
|
|
51
65
|
|
|
52
|
-
Use this when
|
|
66
|
+
Use this path when the platform operator has registered an identity provider and
|
|
67
|
+
the agent holds a valid HMAC identity token or ES256 JWT.
|
|
53
68
|
|
|
54
69
|
```ts
|
|
55
70
|
import { BalchemyAgentSdk } from "@balchemyai/agent-sdk";
|
|
@@ -59,9 +74,9 @@ const sdk = new BalchemyAgentSdk({
|
|
|
59
74
|
});
|
|
60
75
|
|
|
61
76
|
const response = await sdk.onboardWithIdentity({
|
|
62
|
-
provider: "
|
|
63
|
-
identityToken: "
|
|
64
|
-
agentId: "
|
|
77
|
+
provider: "registered-provider-id",
|
|
78
|
+
identityToken: "PROVIDER_JWT",
|
|
79
|
+
agentId: "agent-example",
|
|
65
80
|
chainId: 8453,
|
|
66
81
|
scope: "trade",
|
|
67
82
|
});
|
|
@@ -72,54 +87,54 @@ const mcp = sdk.connectMcp({
|
|
|
72
87
|
});
|
|
73
88
|
```
|
|
74
89
|
|
|
75
|
-
|
|
90
|
+
If the endpoint returns `FEATURE_DISABLED`, the backend needs
|
|
91
|
+
`AGENT_WALLETLESS_ONBOARDING_ENABLED=true`.
|
|
92
|
+
|
|
93
|
+
## MCP Calls
|
|
76
94
|
|
|
77
95
|
```ts
|
|
78
|
-
// List available tools
|
|
79
96
|
const { tools } = await mcp.listTools();
|
|
80
97
|
|
|
81
|
-
|
|
82
|
-
|
|
98
|
+
const reply = await mcp.askBot({
|
|
99
|
+
message: "What is the price of SOL?",
|
|
100
|
+
});
|
|
83
101
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
instruction: "Find a low-risk setup on Base with 50 USDC",
|
|
102
|
+
const research = await mcp.agentExecute({
|
|
103
|
+
instruction: "Find low-risk Base setups with deep liquidity.",
|
|
87
104
|
});
|
|
88
105
|
|
|
89
|
-
// EVM quote (read-only, no wallet interaction)
|
|
90
106
|
const quote = await mcp.evmQuote({
|
|
91
107
|
chainId: 8453,
|
|
92
|
-
sellToken: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
93
|
-
buyToken:
|
|
94
|
-
sellAmount: "50000000",
|
|
108
|
+
sellToken: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
109
|
+
buyToken: "0x4200000000000000000000000000000000000006",
|
|
110
|
+
sellAmount: "50000000",
|
|
95
111
|
});
|
|
96
112
|
|
|
97
|
-
|
|
98
|
-
const swap = await mcp.evmSwap({
|
|
113
|
+
const draftSwap = await mcp.evmSwap({
|
|
99
114
|
chainId: 8453,
|
|
100
115
|
sellToken: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
101
|
-
buyToken:
|
|
116
|
+
buyToken: "0x4200000000000000000000000000000000000006",
|
|
102
117
|
sellAmount: "50000000",
|
|
103
|
-
submit:
|
|
118
|
+
submit: false,
|
|
104
119
|
});
|
|
105
120
|
```
|
|
106
121
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
By default the MCP endpoint exposes a curated agent-facing tool set for chat, execution, setup, behavior rules, portfolio/status, and subscriptions.
|
|
122
|
+
`submit: false` creates a draft/pending order. Use execution only when the agent
|
|
123
|
+
has the right scope and the product flow expects on-chain action.
|
|
110
124
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
Tool scopes:
|
|
125
|
+
## Scope
|
|
114
126
|
|
|
115
127
|
| Scope | Access |
|
|
116
|
-
|
|
117
|
-
| `
|
|
118
|
-
| `
|
|
128
|
+
| --- | --- |
|
|
129
|
+
| `read` | Market data, portfolio views, research, status |
|
|
130
|
+
| `trade` | Read tools plus trade execution tools |
|
|
119
131
|
|
|
120
|
-
|
|
132
|
+
The default MCP endpoint exposes a curated agent-facing surface for chat,
|
|
133
|
+
execution, setup, behavior rules, portfolio/status, and subscriptions. Granular
|
|
134
|
+
internal tools stay hidden unless the platform flag
|
|
135
|
+
`MCP_EXPOSE_GRANULAR_TOOLS=true` is enabled for the bot.
|
|
121
136
|
|
|
122
|
-
##
|
|
137
|
+
## Errors
|
|
123
138
|
|
|
124
139
|
All SDK methods throw `AgentSdkError` on failure.
|
|
125
140
|
|
|
@@ -127,64 +142,77 @@ All SDK methods throw `AgentSdkError` on failure.
|
|
|
127
142
|
import { AgentSdkError } from "@balchemyai/agent-sdk";
|
|
128
143
|
import type { AgentSdkErrorCode } from "@balchemyai/agent-sdk";
|
|
129
144
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
145
|
+
type SdkFailure = {
|
|
146
|
+
code: AgentSdkErrorCode;
|
|
147
|
+
message: string;
|
|
148
|
+
details: unknown;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
function toSdkFailure(err: unknown): SdkFailure | null {
|
|
152
|
+
if (!(err instanceof AgentSdkError)) {
|
|
153
|
+
return null;
|
|
138
154
|
}
|
|
155
|
+
|
|
156
|
+
return {
|
|
157
|
+
code: err.code,
|
|
158
|
+
message: err.message,
|
|
159
|
+
details: err.details,
|
|
160
|
+
};
|
|
139
161
|
}
|
|
140
162
|
```
|
|
141
163
|
|
|
164
|
+
Known codes include `auth_error`, `policy_error`, `rate_limit`,
|
|
165
|
+
`provider_auth_error`, `network_error`, `execution_error`, and
|
|
166
|
+
`invalid_response`.
|
|
167
|
+
|
|
142
168
|
## Tool Response Helpers
|
|
143
169
|
|
|
144
170
|
```ts
|
|
145
|
-
import { getToolText,
|
|
171
|
+
import { getToolText, isToolError, parseToolJson } from "@balchemyai/agent-sdk";
|
|
146
172
|
|
|
147
173
|
const response = await mcp.agentPortfolio();
|
|
148
174
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const data = parseToolJson(response); // T | null
|
|
153
|
-
console.log(data);
|
|
154
|
-
}
|
|
175
|
+
const portfolio = isToolError(response)
|
|
176
|
+
? { error: getToolText(response) }
|
|
177
|
+
: { data: parseToolJson(response) };
|
|
155
178
|
```
|
|
156
179
|
|
|
157
|
-
## Token
|
|
180
|
+
## Token Store
|
|
158
181
|
|
|
159
182
|
```ts
|
|
160
183
|
import { TokenStore } from "@balchemyai/agent-sdk";
|
|
161
184
|
|
|
162
185
|
const store = new TokenStore({
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
186
|
+
refreshFn: async () =>
|
|
187
|
+
sdk.onboardWithIdentity({
|
|
188
|
+
provider: "registered-provider-id",
|
|
189
|
+
identityToken: "PROVIDER_JWT",
|
|
190
|
+
agentId: "agent-example",
|
|
191
|
+
chainId: 8453,
|
|
192
|
+
scope: "trade",
|
|
193
|
+
}),
|
|
167
194
|
});
|
|
168
195
|
|
|
169
196
|
await store.set(response);
|
|
170
|
-
const token = await store.get();
|
|
197
|
+
const token = await store.get();
|
|
171
198
|
```
|
|
172
199
|
|
|
200
|
+
The store refreshes when the token is near expiry.
|
|
201
|
+
|
|
173
202
|
## Identity Access Token
|
|
174
203
|
|
|
175
|
-
|
|
204
|
+
`OnboardingResponse` includes `identityAccess` when the platform issues a
|
|
205
|
+
short-lived identity access token beside the MCP key.
|
|
176
206
|
|
|
177
207
|
```ts
|
|
178
208
|
import type { IdentityAccess } from "@balchemyai/agent-sdk";
|
|
179
209
|
|
|
180
210
|
const access: IdentityAccess | undefined = response.identityAccess;
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
console.log(access.expiresAt); // ISO timestamp
|
|
184
|
-
}
|
|
211
|
+
const scope = access?.scope;
|
|
212
|
+
const expiresAt = access?.expiresAt;
|
|
185
213
|
```
|
|
186
214
|
|
|
187
|
-
## SSE
|
|
215
|
+
## SSE Events
|
|
188
216
|
|
|
189
217
|
```ts
|
|
190
218
|
import { SseEventStream } from "@balchemyai/agent-sdk";
|
|
@@ -196,34 +224,34 @@ const stream = new SseEventStream(
|
|
|
196
224
|
{ reconnectDelayMs: 2000, maxReconnects: 0 }
|
|
197
225
|
);
|
|
198
226
|
|
|
199
|
-
|
|
200
|
-
for await (const event of stream) {
|
|
201
|
-
|
|
202
|
-
|
|
227
|
+
async function readEvents() {
|
|
228
|
+
for await (const event of stream) {
|
|
229
|
+
handleEvent(event);
|
|
230
|
+
}
|
|
203
231
|
}
|
|
204
232
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
(err) => console.error(err)
|
|
209
|
-
);
|
|
210
|
-
// later: unsubscribe();
|
|
233
|
+
function handleEvent(event: SseEvent) {
|
|
234
|
+
return event;
|
|
235
|
+
}
|
|
211
236
|
```
|
|
212
237
|
|
|
213
238
|
## Identity Token Revocation
|
|
214
239
|
|
|
215
240
|
```ts
|
|
216
|
-
|
|
217
|
-
|
|
241
|
+
await sdk.revokeIdentityToken({
|
|
242
|
+
jti: "token-jti",
|
|
243
|
+
ttlSeconds: 86400,
|
|
244
|
+
});
|
|
218
245
|
|
|
219
|
-
|
|
220
|
-
|
|
246
|
+
const { revoked } = await sdk.getIdentityTokenRevokeStatus({
|
|
247
|
+
jti: "token-jti",
|
|
248
|
+
});
|
|
221
249
|
```
|
|
222
250
|
|
|
223
|
-
## Platform Endpoints
|
|
251
|
+
## Platform Endpoints
|
|
224
252
|
|
|
225
253
|
| Endpoint | Path | Auth |
|
|
226
|
-
|
|
254
|
+
| --- | --- | --- |
|
|
227
255
|
| MCP server | `POST /api/mcp/{publicId}` | `Authorization: Bearer <mcp-api-key>` |
|
|
228
256
|
| SIWE nonce | `POST /api/nest/auth/evm/nonce` | Public |
|
|
229
257
|
| SIWE onboarding | `POST /api/public/erc8004/onboarding/siwe` | Public |
|
|
@@ -233,45 +261,25 @@ const { revoked } = await sdk.getIdentityTokenRevokeStatus({ jti: "the-token-jti
|
|
|
233
261
|
| MCP discovery | `GET /.well-known/mcp.json` | Public |
|
|
234
262
|
| Agent directory | `GET /api/nest/agents/verified/page` | Public |
|
|
235
263
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
## Platform Operator Setup
|
|
264
|
+
JWKS is root-relative. Do not prefix it with `/api`.
|
|
239
265
|
|
|
240
|
-
|
|
266
|
+
## Operator Setup
|
|
241
267
|
|
|
242
268
|
| Variable | Required | Description |
|
|
243
|
-
|
|
244
|
-
| `AGENT_WALLETLESS_ONBOARDING_ENABLED` |
|
|
245
|
-
| `SIWE_DOMAIN_ALLOWLIST` |
|
|
246
|
-
| `ERC8004_IDENTITY_PROVIDERS` |
|
|
247
|
-
| `AGENT_IDENTITY_ISSUER_PRIVATE_KEY_PEM` |
|
|
248
|
-
| `API_URL` | Always | Base API URL used to build MCP endpoint URLs
|
|
249
|
-
|
|
250
|
-
## Getting Started (Quickstart)
|
|
251
|
-
|
|
252
|
-
1. Install the SDK:
|
|
253
|
-
```sh
|
|
254
|
-
npm install @balchemyai/agent-sdk
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
2. Create an MCP API key for your bot via the Hub UI: `Hub > Your Bot > API Keys > Create Key`.
|
|
258
|
-
|
|
259
|
-
3. Choose an auth path:
|
|
260
|
-
- **SIWE (wallet-based):** Your agent must control an EVM wallet and can sign messages.
|
|
261
|
-
- **Walletless (identity token):** Your agent has an HMAC-signed identity token (balchemy native) or ES256 JWT (external provider) from a registered provider. The platform operator must set `AGENT_WALLETLESS_ONBOARDING_ENABLED=true`.
|
|
262
|
-
|
|
263
|
-
4. Run the relevant code example in the [Auth Paths](#auth-paths) section above.
|
|
264
|
-
|
|
265
|
-
5. Use the returned `mcp.endpoint` and `mcp.apiKey` to make MCP tool calls.
|
|
266
|
-
|
|
267
|
-
6. The MCP key is scoped — `"read"` for read-only tools, `"trade"` for trade execution tools. Choose at onboarding time via the `scope` parameter.
|
|
269
|
+
| --- | --- | --- |
|
|
270
|
+
| `AGENT_WALLETLESS_ONBOARDING_ENABLED` | Walletless path | Enables identity onboarding. Default: `false`. |
|
|
271
|
+
| `SIWE_DOMAIN_ALLOWLIST` | SIWE path | Comma-separated domains allowed in SIWE verification. |
|
|
272
|
+
| `ERC8004_IDENTITY_PROVIDERS` | Walletless path | Registered provider IDs. |
|
|
273
|
+
| `AGENT_IDENTITY_ISSUER_PRIVATE_KEY_PEM` | Identity tokens | ES256 private key for short-lived identity access tokens. |
|
|
274
|
+
| `API_URL` | Always | Base API URL used to build MCP endpoint URLs. |
|
|
268
275
|
|
|
269
276
|
## Notes
|
|
270
277
|
|
|
271
|
-
- `agent_seed_request` is disabled on the platform.
|
|
272
|
-
- `
|
|
273
|
-
|
|
274
|
-
-
|
|
278
|
+
- `agent_seed_request` is disabled on the platform.
|
|
279
|
+
- `requestSeed()` remains for compatibility and throws `AgentSdkError` with
|
|
280
|
+
code `execution_error`.
|
|
281
|
+
- MCP keys are scoped. Choose `read` or `trade` during onboarding.
|
|
282
|
+
- Walletless onboarding requires an operator-approved provider.
|
|
275
283
|
|
|
276
284
|
## Docs
|
|
277
285
|
|
|
@@ -279,4 +287,4 @@ To enable agent onboarding, the following environment variables must be configur
|
|
|
279
287
|
- [Python parity backlog](docs/python-parity-backlog.md)
|
|
280
288
|
- [Partner integration checklist](docs/partner-integration-checklist.md)
|
|
281
289
|
- [Release policy](docs/release-policy.md)
|
|
282
|
-
- Full API reference
|
|
290
|
+
- [Full API reference](https://balchemy.ai/docs)
|
package/docs/QUICKSTART.md
CHANGED
|
@@ -88,6 +88,10 @@ const loop = AgentLoop.fromConfig('./agent.config.yaml');
|
|
|
88
88
|
await loop.start();
|
|
89
89
|
|
|
90
90
|
// Or inline config
|
|
91
|
+
const statusEvents: string[] = [];
|
|
92
|
+
const decisionEvents: unknown[] = [];
|
|
93
|
+
const errorEvents: string[] = [];
|
|
94
|
+
|
|
91
95
|
const loop2 = new AgentLoop({
|
|
92
96
|
mcpEndpoint: 'https://api.balchemy.ai/mcp/YOUR_PUBLIC_ID',
|
|
93
97
|
apiKey: process.env.BALCHEMY_API_KEY!,
|
|
@@ -95,9 +99,9 @@ const loop2 = new AgentLoop({
|
|
|
95
99
|
llmApiKey: process.env.ANTHROPIC_API_KEY!,
|
|
96
100
|
llmModel: 'claude-haiku-4-5',
|
|
97
101
|
maxDailyLlmCost: 5,
|
|
98
|
-
onStatusChange: (s) =>
|
|
99
|
-
onDecision: (d) =>
|
|
100
|
-
onError: (e) =>
|
|
102
|
+
onStatusChange: (s) => statusEvents.push(s.status),
|
|
103
|
+
onDecision: (d) => decisionEvents.push(d),
|
|
104
|
+
onError: (e) => errorEvents.push(e.message),
|
|
101
105
|
});
|
|
102
106
|
await loop2.start();
|
|
103
107
|
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@balchemyai/agent-sdk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "Balchemy external AI agent onboarding + MCP SDK — ERC-8004 onboarding, Solana/EVM trading, 100 tools via MCP",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"homepage": "https://balchemy.ai",
|
|
39
39
|
"repository": {
|
|
40
40
|
"type": "git",
|
|
41
|
-
"url": "https://github.com/balchemy/balchemy-agent",
|
|
41
|
+
"url": "git+https://github.com/balchemy/balchemy-agent.git",
|
|
42
42
|
"directory": "packages/sdk"
|
|
43
43
|
},
|
|
44
44
|
"bugs": {
|