agentid-sdk 0.1.36 → 0.1.38

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 CHANGED
@@ -87,18 +87,16 @@ await agent.log({
87
87
  npm install agentid-sdk openai
88
88
  ```
89
89
 
90
- ```ts
91
- import OpenAI from "openai";
92
- import { AgentID } from "agentid-sdk";
93
-
94
- const agent = new AgentID({
95
- piiMasking: true,
96
- });
97
-
98
- const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY! });
99
- const secured = agent.wrapOpenAI(openai, {
100
- system_id: process.env.AGENTID_SYSTEM_ID!,
101
- user_id: "customer-123",
90
+ ```ts
91
+ import OpenAI from "openai";
92
+ import { AgentID } from "agentid-sdk";
93
+
94
+ const agent = new AgentID();
95
+
96
+ const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY! });
97
+ const secured = agent.wrapOpenAI(openai, {
98
+ system_id: process.env.AGENTID_SYSTEM_ID!,
99
+ user_id: "customer-123",
102
100
  expected_languages: ["en"],
103
101
  });
104
102
 
@@ -107,8 +105,24 @@ const response = await secured.chat.completions.create({
107
105
  messages: [{ role: "user", content: "What is the capital of the Czech Republic?" }],
108
106
  });
109
107
 
110
- console.log(response.choices[0]?.message?.content ?? "");
111
- ```
108
+ console.log(response.choices[0]?.message?.content ?? "");
109
+ ```
110
+
111
+ By default, official AgentID SDK integrations inherit `enable_sdk_pii_masking`
112
+ from the dashboard/runtime config. You only need to set `piiMasking: true` in
113
+ code if you want to force local masking on even when the dashboard policy is off.
114
+
115
+ When SDK-side masking is enabled, the wrapper now masks both classic PII and
116
+ high-confidence secret material before the request leaves your process:
117
+
118
+ - emails, phones, card numbers, IBANs, national IDs, person names
119
+ - OpenAI / Anthropic / Google / AWS / GitHub / Slack / Stripe credentials
120
+ - bearer tokens, JWTs, `x-api-key` headers
121
+ - password / credential assignments, PEM private keys, Azure connection strings and SAS tokens
122
+
123
+ The masked form is what gets sent to `/guard`, logged to AgentID ingest, and
124
+ forwarded to the model provider. Placeholder mapping stays local to the SDK and
125
+ can be deanonymized back to the caller after completion.
112
126
 
113
127
  Wrapped OpenAI calls persist telemetry for both regular and streamed completions. For `stream: true`, logging happens when the stream finishes.
114
128
 
@@ -131,17 +145,30 @@ npm install agentid-sdk openai @langchain/core @langchain/openai
131
145
  ```
132
146
 
133
147
  ```ts
134
- import { AgentID } from "agentid-sdk";
135
- import { AgentIDCallbackHandler } from "agentid-sdk/langchain";
136
- import { ChatOpenAI } from "@langchain/openai";
137
- import { ChatPromptTemplate } from "@langchain/core/prompts";
138
- import { StringOutputParser } from "@langchain/core/output_parsers";
139
-
140
- const agent = new AgentID();
141
- const handler = new AgentIDCallbackHandler(agent, {
142
- system_id: process.env.AGENTID_SYSTEM_ID!,
143
- expected_languages: ["en"],
144
- });
148
+ import {
149
+ AgentID,
150
+ createAgentIdCorrelationId,
151
+ createAgentIdTelemetryContext,
152
+ } from "agentid-sdk";
153
+ import { AgentIDCallbackHandler } from "agentid-sdk/langchain";
154
+ import { ChatOpenAI } from "@langchain/openai";
155
+ import { ChatPromptTemplate } from "@langchain/core/prompts";
156
+ import { StringOutputParser } from "@langchain/core/output_parsers";
157
+
158
+ const agent = new AgentID();
159
+ const workflowRunId = createAgentIdCorrelationId();
160
+ const handler = new AgentIDCallbackHandler(agent, {
161
+ system_id: process.env.AGENTID_SYSTEM_ID!,
162
+ expected_languages: ["en"],
163
+ telemetry: createAgentIdTelemetryContext({
164
+ workflowRunId,
165
+ workflowStepName: "answer_question",
166
+ toolName: "langchain.chat",
167
+ toolTargetType: "conversation",
168
+ eventCategory: "ai",
169
+ eventSubtype: "answer_generated",
170
+ }),
171
+ });
145
172
 
146
173
  const prompt = ChatPromptTemplate.fromTemplate("Answer in one sentence: {question}");
147
174
  const model = new ChatOpenAI({
@@ -155,14 +182,19 @@ const result = await chain.invoke(
155
182
  { callbacks: [handler] }
156
183
  );
157
184
  console.log(result);
158
- ```
159
-
160
- LangChain callbacks log on run completion. Token/cost telemetry for streamed chains depends on the provider exposing usage in the final LangChain result.
161
-
162
- ### Raw Ingest API (Telemetry Only)
163
-
164
- ```ts
165
- import { AgentID } from "agentid-sdk";
185
+ ```
186
+
187
+ LangChain callbacks log on run completion. Constructor-level `telemetry` is copied
188
+ to the guard request, local policy telemetry, and final ingest log. You can
189
+ override or extend it per invocation with LangChain metadata:
190
+ `{ metadata: { agentid_telemetry: { workflowStepName: "..." } } }`.
191
+ Token/cost telemetry for streamed chains depends on the provider exposing usage
192
+ in the final LangChain result.
193
+
194
+ ### Raw Ingest API (Telemetry Only)
195
+
196
+ ```ts
197
+ import { AgentID } from "agentid-sdk";
166
198
 
167
199
  const agent = new AgentID();
168
200
 
@@ -173,11 +205,100 @@ await agent.log({
173
205
  model: "gpt-4o-mini",
174
206
  input: "Raw telemetry prompt",
175
207
  output: '{"ok": true}',
176
- metadata: { agent_role: "batch-worker", channel: "manual_ingest" },
177
- });
178
- ```
179
-
180
- ### Transparency Badge (Article 50 UI Evidence)
208
+ metadata: { agent_role: "batch-worker", channel: "manual_ingest" },
209
+ });
210
+ ```
211
+
212
+ ### Agent workflow and tool events
213
+
214
+ Use `logOperation()` when an agent calls tools or performs operational work outside the wrapped LLM call. Reuse the same `workflowRunId` across steps.
215
+
216
+ ```ts
217
+ import {
218
+ AgentID,
219
+ createAgentIdCorrelationId,
220
+ createAgentIdTelemetryContext,
221
+ } from "agentid-sdk";
222
+
223
+ const agent = new AgentID();
224
+ const workflowRunId = createAgentIdCorrelationId();
225
+
226
+ await agent.logOperation({
227
+ system_id: process.env.AGENTID_SYSTEM_ID!,
228
+ telemetry: createAgentIdTelemetryContext({
229
+ workflowRunId,
230
+ workflowStepName: "screen_candidate",
231
+ toolName: "hr.cv_screen",
232
+ toolTargetType: "candidate",
233
+ }),
234
+ event_category: "tool",
235
+ event_status: "completed",
236
+ });
237
+
238
+ await agent.logOperation({
239
+ system_id: process.env.AGENTID_SYSTEM_ID!,
240
+ telemetry: createAgentIdTelemetryContext({
241
+ workflowRunId,
242
+ workflowStepName: "send_followup",
243
+ toolName: "email.send",
244
+ toolTargetType: "email",
245
+ }),
246
+ event_category: "delivery",
247
+ event_status: "completed",
248
+ });
249
+ ```
250
+
251
+ Tool, delivery, inbox, workflow, guard, and operational events are logged as separate audit rows. They are grouped in the dashboard by `workflow_run_id` and do not count as model-used or spend-bearing unless you explicitly provide model/usage data. Do not reuse one `client_event_id` for the whole workflow; use `workflowRunId` for grouping and let each event keep its own idempotency key.
252
+
253
+ Dashboard behavior:
254
+
255
+ - prompt/guard checks remain visible as standalone Activity rows with `View Details` and `View Prompt`
256
+ - workflow summary rows open the grouped timeline with tools, delivery, inbox, workflow lifecycle, guard checks, and LLM steps
257
+ - the workflow timeline is operational context; the standalone prompt row is the forensic prompt inspection surface
258
+ - non-model workflow/tool/delivery rows show `Model: Not applicable` and are not spend-bearing unless model/cost metadata is explicitly present
259
+
260
+ For full agent runs, prefer the workflow trail helper so each step gets a shared
261
+ `workflow_step_id`, plus automatic `started/completed/failed` rows:
262
+
263
+ ```ts
264
+ import {
265
+ AgentID,
266
+ createAgentIdCorrelationId,
267
+ createAgentIdTelemetryContext,
268
+ createAgentIdWorkflowTrail,
269
+ } from "agentid-sdk";
270
+
271
+ const agent = new AgentID({ apiKey: process.env.AGENTID_API_KEY! });
272
+ const workflowRunId = createAgentIdCorrelationId();
273
+
274
+ const trail = createAgentIdWorkflowTrail({
275
+ agent,
276
+ system_id: process.env.AGENTID_SYSTEM_ID!,
277
+ telemetry: createAgentIdTelemetryContext({
278
+ workflowRunId,
279
+ workflowName: "Candidate intake",
280
+ }),
281
+ });
282
+
283
+ await trail.runStep(
284
+ {
285
+ telemetry: createAgentIdTelemetryContext({
286
+ workflowStepName: "screen_candidate",
287
+ toolName: "hr.cv_screen",
288
+ toolTargetType: "candidate",
289
+ eventCategory: "tool",
290
+ }),
291
+ },
292
+ async () => screenCandidate(),
293
+ {
294
+ complete: {
295
+ metadata: { result_count: 4 },
296
+ },
297
+ }
298
+ );
299
+ ```
300
+
301
+ ### Transparency Badge (Article 50 UI Evidence)
181
302
 
182
303
  When rendering disclosure UI, log proof-of-render telemetry so you can demonstrate the end-user actually saw the badge.
183
304
 
@@ -249,11 +370,25 @@ By default, AgentID is designed to keep your application running if the AgentID
249
370
 
250
371
  - `guard()` returns a verdict (`allowed`, `reason`); handle deny paths explicitly.
251
372
  - `wrapOpenAI()` and LangChain handlers throw `SecurityBlockError` when a prompt is blocked.
252
- - Backend `/guard` is the default authority for prompt injection, DB access, code execution, and PII leakage in SDK-wrapped flows.
253
- - `clientFastFail` / `client_fast_fail` is optional and disabled by default. Enable it only when you explicitly want local preflight before the backend call.
254
- - If backend guard is unreachable and the effective failure mode is `fail_close`, wrapped OpenAI/LangChain flows can run local fallback enforcement. Local hits still block; otherwise the request can continue with fallback telemetry attached.
255
- - If `strictMode` is not explicitly set in SDK code, runtime behavior follows the system configuration from AgentID (`strict_security_mode` / `failure_mode`).
256
- - Ingest retries transient failures (5xx/429) and logs warnings if persistence fails.
373
+ - Backend `/guard` is the default authority for prompt injection, DB access, code execution, and PII leakage in SDK-wrapped flows.
374
+ - `clientFastFail` / `client_fast_fail` is optional and disabled by default. Enable it only when you explicitly want local preflight before the backend call.
375
+ - If backend guard is unreachable and the effective failure mode is `fail_close`, wrapped OpenAI/LangChain flows can run local fallback enforcement. Local hits still block; otherwise the request can continue with fallback telemetry attached.
376
+ - If `strictMode` is not explicitly set in SDK code, runtime behavior follows the system configuration from AgentID (`strict_security_mode` / `failure_mode`).
377
+ - Ingest retries transient failures (5xx/429) and logs warnings if persistence fails.
378
+
379
+ ### SDK-side masking scope
380
+
381
+ If `enable_sdk_pii_masking=true` in AgentID runtime config, or if you force
382
+ `piiMasking: true` in code, masking happens locally before `/guard` and before
383
+ provider dispatch.
384
+
385
+ - Default mode: backend-first enforcement, optional local masking
386
+ - `clientFastFail=false`: no local prompt/code/db blocker, but local masking can still rewrite prompt text before network dispatch
387
+ - `clientFastFail=true`: local prompt-injection scan and strict local enforcement can run before `/guard`
388
+
389
+ This means SDK masking is useful even when you keep backend guard as the main
390
+ policy authority: it reduces raw data exposure on the wire without changing the
391
+ server-side decision model.
257
392
 
258
393
  ### Event Identity Model
259
394
 
@@ -261,7 +396,7 @@ For consistent lifecycle correlation in Activity/Prompts, use this model:
261
396
 
262
397
  - `client_event_id`: external correlation ID for one end-to-end action.
263
398
  - `guard_event_id`: ID of the preflight guard event returned by `guard()`.
264
- - `event_id` on `log()`: idempotency key for ingest. In the JS SDK it is canonicalized to `client_event_id` for stable one-row lifecycle updates.
399
+ - `event_id` on `log()`: idempotency key for ingest. In `agentid-sdk` it is canonicalized to `client_event_id` for stable one-row lifecycle updates.
265
400
 
266
401
  SDK behavior:
267
402
 
@@ -287,7 +422,7 @@ SDK-managed metadata can include:
287
422
 
288
423
  ### Policy-Pack Runtime Telemetry
289
424
 
290
- When the backend uses compiled policy packs, runtime metadata includes:
425
+ When the backend uses compiled policy packs, runtime metadata includes:
291
426
 
292
427
  - `policy_pack_version`: active compiled artifact version.
293
428
  - `policy_pack_fallback`: `true` means fallback detector path was used.
@@ -297,7 +432,23 @@ Latency interpretation:
297
432
 
298
433
  - Activity `Latency (ms)` maps to synchronous processing (`processing_time_ms`).
299
434
  - Async AI audit time is separate (`ai_audit_duration_ms`) and can be higher.
300
- - First request after warm-up boundaries can be slower than steady-state requests.
435
+ - First request after warm-up boundaries can be slower than steady-state requests.
436
+
437
+ ### Secret and PII Masking Edge Cases
438
+
439
+ SDK-side masking and the backend scanner include regression coverage for common
440
+ boundary failures:
441
+
442
+ - multiline PEM, certificate, and PGP private key blocks
443
+ - natural-language password disclosures such as `my Password is Passwordk123`
444
+ - environment-style assignments such as `DB_PASSWORD=...`
445
+ - secret values with suffix punctuation such as `#`
446
+ - high-entropy base64-like values with `=` / `==` padding
447
+ - security-question answers where the value appears after `answer is`, `is`, or localized equivalents
448
+
449
+ When local masking is enabled, these values are replaced before provider
450
+ dispatch and before AgentID ingest. Placeholder mappings stay local to the SDK
451
+ for reversible deanonymization.
301
452
 
302
453
  ### Monorepo QA Commands (Maintainers)
303
454
 
@@ -317,21 +468,27 @@ powershell -ExecutionPolicy Bypass -File .\scripts\qa\run-ai-label-audit-check.p
317
468
 
318
469
  ## 7. Security & Compliance
319
470
 
320
- - Backend `/guard` remains the primary enforcement authority by default.
321
- - Optional local PII masking and opt-in `clientFastFail` are available for edge cases.
322
- - Guard checks run pre-execution; ingest + finalize telemetry captures prompt/output lifecycle and SDK timing breakdowns.
323
- - Safe for server and serverless runtimes (including async completion flows).
324
- - Supports compliance and forensics workflows with durable event records.
325
-
326
- ## 8. Support
327
-
328
- - Dashboard: `https://app.getagentid.com`
329
- - Repository: `https://github.com/ondrejsukac-rgb/agentid/tree/main/js-sdk`
330
- - Issues: `https://github.com/ondrejsukac-rgb/agentid/issues`
331
-
332
- ## 9. Publishing Notes (NPM)
333
-
334
- NPM automatically renders `README.md` from the package root during `npm publish`.
335
-
336
- - File location: next to `package.json` in `js-sdk/`.
337
- - No additional NPM config is required for README rendering.
471
+ - Backend `/guard` remains the primary enforcement authority by default.
472
+ - Optional local masking and opt-in `clientFastFail` are available for edge cases.
473
+ - SDK-side masking can now cover both structured PII and high-confidence leaked secrets before provider dispatch.
474
+ - Guard checks run pre-execution; ingest + finalize telemetry captures prompt/output lifecycle and SDK timing breakdowns.
475
+ - Safe for server and serverless runtimes (including async completion flows).
476
+ - Supports compliance and forensics workflows with durable event records.
477
+
478
+ ## 8. Support
479
+
480
+ - Dashboard: `https://app.getagentid.com`
481
+ - Documentation: `https://docs.getagentid.com/docs/node-typescript-sdk`
482
+ - Repository: `https://github.com/ondrejsukac-rgb/agentid/tree/main/agentid-sdk`
483
+ - Issues: `https://github.com/ondrejsukac-rgb/agentid/issues`
484
+
485
+ ## 9. Publishing Notes (NPM)
486
+
487
+ NPM automatically renders `README.md` from the package root during `npm publish`.
488
+
489
+ - File location: next to `package.json` in `agentid-sdk/`.
490
+ - No additional NPM config is required for README rendering.
491
+ - Before publishing from the monorepo, run `npm run audit:all` and
492
+ `npm run qa:production-gate` from the repository root.
493
+ - The production gate audits the root app, `agentid-sdk`, `agentid-vercel-sdk`, and
494
+ the browser extension package so package-local lockfile issues are not missed.