agentid-sdk 0.1.37 → 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
@@ -111,6 +111,18 @@ console.log(response.choices[0]?.message?.content ?? "");
111
111
  By default, official AgentID SDK integrations inherit `enable_sdk_pii_masking`
112
112
  from the dashboard/runtime config. You only need to set `piiMasking: true` in
113
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.
114
126
 
115
127
  Wrapped OpenAI calls persist telemetry for both regular and streamed completions. For `stream: true`, logging happens when the stream finishes.
116
128
 
@@ -133,17 +145,30 @@ npm install agentid-sdk openai @langchain/core @langchain/openai
133
145
  ```
134
146
 
135
147
  ```ts
136
- import { AgentID } from "agentid-sdk";
137
- import { AgentIDCallbackHandler } from "agentid-sdk/langchain";
138
- import { ChatOpenAI } from "@langchain/openai";
139
- import { ChatPromptTemplate } from "@langchain/core/prompts";
140
- import { StringOutputParser } from "@langchain/core/output_parsers";
141
-
142
- const agent = new AgentID();
143
- const handler = new AgentIDCallbackHandler(agent, {
144
- system_id: process.env.AGENTID_SYSTEM_ID!,
145
- expected_languages: ["en"],
146
- });
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
+ });
147
172
 
148
173
  const prompt = ChatPromptTemplate.fromTemplate("Answer in one sentence: {question}");
149
174
  const model = new ChatOpenAI({
@@ -157,14 +182,19 @@ const result = await chain.invoke(
157
182
  { callbacks: [handler] }
158
183
  );
159
184
  console.log(result);
160
- ```
161
-
162
- LangChain callbacks log on run completion. Token/cost telemetry for streamed chains depends on the provider exposing usage in the final LangChain result.
163
-
164
- ### Raw Ingest API (Telemetry Only)
165
-
166
- ```ts
167
- 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";
168
198
 
169
199
  const agent = new AgentID();
170
200
 
@@ -175,11 +205,100 @@ await agent.log({
175
205
  model: "gpt-4o-mini",
176
206
  input: "Raw telemetry prompt",
177
207
  output: '{"ok": true}',
178
- metadata: { agent_role: "batch-worker", channel: "manual_ingest" },
179
- });
180
- ```
181
-
182
- ### 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)
183
302
 
184
303
  When rendering disclosure UI, log proof-of-render telemetry so you can demonstrate the end-user actually saw the badge.
185
304
 
@@ -251,11 +370,25 @@ By default, AgentID is designed to keep your application running if the AgentID
251
370
 
252
371
  - `guard()` returns a verdict (`allowed`, `reason`); handle deny paths explicitly.
253
372
  - `wrapOpenAI()` and LangChain handlers throw `SecurityBlockError` when a prompt is blocked.
254
- - Backend `/guard` is the default authority for prompt injection, DB access, code execution, and PII leakage in SDK-wrapped flows.
255
- - `clientFastFail` / `client_fast_fail` is optional and disabled by default. Enable it only when you explicitly want local preflight before the backend call.
256
- - 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.
257
- - If `strictMode` is not explicitly set in SDK code, runtime behavior follows the system configuration from AgentID (`strict_security_mode` / `failure_mode`).
258
- - 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.
259
392
 
260
393
  ### Event Identity Model
261
394
 
@@ -263,7 +396,7 @@ For consistent lifecycle correlation in Activity/Prompts, use this model:
263
396
 
264
397
  - `client_event_id`: external correlation ID for one end-to-end action.
265
398
  - `guard_event_id`: ID of the preflight guard event returned by `guard()`.
266
- - `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.
267
400
 
268
401
  SDK behavior:
269
402
 
@@ -289,7 +422,7 @@ SDK-managed metadata can include:
289
422
 
290
423
  ### Policy-Pack Runtime Telemetry
291
424
 
292
- When the backend uses compiled policy packs, runtime metadata includes:
425
+ When the backend uses compiled policy packs, runtime metadata includes:
293
426
 
294
427
  - `policy_pack_version`: active compiled artifact version.
295
428
  - `policy_pack_fallback`: `true` means fallback detector path was used.
@@ -299,7 +432,23 @@ Latency interpretation:
299
432
 
300
433
  - Activity `Latency (ms)` maps to synchronous processing (`processing_time_ms`).
301
434
  - Async AI audit time is separate (`ai_audit_duration_ms`) and can be higher.
302
- - 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.
303
452
 
304
453
  ### Monorepo QA Commands (Maintainers)
305
454
 
@@ -319,21 +468,27 @@ powershell -ExecutionPolicy Bypass -File .\scripts\qa\run-ai-label-audit-check.p
319
468
 
320
469
  ## 7. Security & Compliance
321
470
 
322
- - Backend `/guard` remains the primary enforcement authority by default.
323
- - Optional local PII masking and opt-in `clientFastFail` are available for edge cases.
324
- - Guard checks run pre-execution; ingest + finalize telemetry captures prompt/output lifecycle and SDK timing breakdowns.
325
- - Safe for server and serverless runtimes (including async completion flows).
326
- - Supports compliance and forensics workflows with durable event records.
327
-
328
- ## 8. Support
329
-
330
- - Dashboard: `https://app.getagentid.com`
331
- - Repository: `https://github.com/ondrejsukac-rgb/agentid/tree/main/js-sdk`
332
- - Issues: `https://github.com/ondrejsukac-rgb/agentid/issues`
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.
333
477
 
334
- ## 9. Publishing Notes (NPM)
335
-
336
- NPM automatically renders `README.md` from the package root during `npm publish`.
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`
337
484
 
338
- - File location: next to `package.json` in `js-sdk/`.
339
- - No additional NPM config is required for README rendering.
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.