Skip to content
AgentIDDocs

Type at least two characters to search titles, headings and content.

↑ ↓ to navigate↵ to open
AgentID Docs

SDKs & API

Node.js / TypeScript SDK

Guard, mask and log LLM calls from Node.js with agentid-sdk, including an OpenAI wrapper, LangChain callbacks and workflow telemetry.

agentid-sdk (version 0.1.43) runs on Node.js 18 or later, in server and serverless runtimes.

Install

npm install agentid-sdk openai
export AGENTID_API_KEY="sk_live_..."
export AGENTID_SYSTEM_ID="00000000-0000-0000-0000-000000000000"

Initialize

import { AgentID } from "agentid-sdk";

const agent = new AgentID(); // reads AGENTID_API_KEY

Create one instance and reuse it across requests.

apiKeystring

API key. Defaults to AGENTID_API_KEY.

baseUrlstring

Defaults to https://app.getagentid.com/api/v1.

strictModeboolean

Fail-closed on Guard connectivity failures. Cannot be combined with failureMode: fail_open.

failureMode"fail_open" | "fail_close"

Overrides the system's failure mode. Omit to follow the dashboard.

piiMaskingboolean

Force local masking of personal data. Omit to follow the dashboard.

secretMaskingboolean

Force local masking of secrets. Omit to follow the dashboard.

clientFastFailboolean

Run a local prompt-injection preflight before Guard. Off by default.

guardTimeoutMsnumber

Guard timeout, default 30000 (500 to 120000).

ingestTimeoutMsnumber

Ingest timeout, default 10000 (500 to 15000).

Wrap the OpenAI client

The wrapper guards, masks and logs every chat.completions.create call, including stream: true (logged when the stream ends).

chat.tsTypeScript
import OpenAI from "openai";
import { AgentID, SecurityBlockError } from "agentid-sdk";

const agent = new AgentID();
const openai = agent.wrapOpenAI(new OpenAI(), {
  system_id: process.env.AGENTID_SYSTEM_ID!,
  user_id: "customer-123",
  expected_languages: ["en"],
});

try {
  const response = await openai.chat.completions.create({
    model: "gpt-4o-mini",
    messages: fullConversationHistory,
  });
  console.log(response.choices[0]?.message?.content);
} catch (error) {
  if (error instanceof SecurityBlockError) {
    console.error("Blocked by AgentID:", error.reason);
  } else {
    throw error;
  }
}

wrapOpenAI(openai, options) options: system_id (required), user_id, expected_languages, request_identity, telemetry, apiKey or resolveApiKey(request), and deanonymizeOutputForClient.

Its pre-flight guard() input is the last user message (plus supported inline attachments on it). With SDK-side masking on, the full history sent to the provider is masked locally.

Manual guard and log

manual.tsTypeScript
import { AgentID } from "agentid-sdk";

const agent = new AgentID();
const systemId = process.env.AGENTID_SYSTEM_ID!;

const verdict = await agent.guard({
  system_id: systemId,
  input: userMessage,
  model: "gpt-4o-mini",
  user_id: "customer-123",
});
if (!verdict.allowed) throw new Error(`Blocked: ${verdict.reason}`);

const protectedInput = verdict.transformed_input ?? userMessage;
const started = Date.now();
const completion = await callModel(protectedInput);

await agent.log({
  system_id: systemId,
  event_id: verdict.client_event_id,
  model: "gpt-4o-mini",
  input: protectedInput,
  output: completion.text,
  usage: completion.usage,
  latency: Date.now() - started,
});

guard(params, options?) accepts the Guard request fields (input, system_id, prompt_context, attachments, model, user_id, client_event_id, expected_languages, request_identity, metadata, pii_detection_mode). options.apiKey overrides the key for one call.

Masking and restoration

  • The wrappers follow Mask Personal Information and Mask Secrets & API Keys from the dashboard. Set piiMasking / secretMasking only to force local masking on.
  • Local masking covers e-mails, phone numbers, card numbers, IBANs, national IDs, person names, provider API keys and tokens, bearer tokens and JWTs, password and credential assignments, PEM private keys, and Azure connection strings and SAS tokens. It produces placeholders such as <PERSON_1> and <EMAIL_1>.
  • From version 0.1.40, local masking stays on when Guard or the configuration endpoint is unreachable in fail-open mode.
  • With Restore masked values for the end user on, the wrapper restores placeholders in the result returned to your code; the provider request and AgentID's logs stay masked. Opt out per wrapper with deanonymizeOutputForClient: false.

For your own routes, protect the exact history you send:

import { protectMessageHistory, protectChatState } from "agentid-sdk";

const protectedHistory = protectMessageHistory(body.messages, { pii: true, secrets: true });
await provider.chat.completions.create({ model: "gpt-4o-mini", messages: protectedHistory.messages });

// Separate views for UI, provider and storage:
const chat = protectChatState(body.messages, {
  transcript: { ui: "raw", provider: "masked", persistence: "masked" },
});

protectMessageHistory returns messages, transformed, textPartsCount, transformedTextPartsCount and placeholderMapping. Keep the mapping in memory; do not persist it.

PIIManager gives direct access: new PIIManager().anonymize(text, { pii, secrets }) returns { maskedText, mapping }, and deanonymize(text, mapping) restores it.

LangChain

chain.tsTypeScript
import { AgentID } from "agentid-sdk";
import { AgentIDCallbackHandler } from "agentid-sdk/langchain";
import { ChatOpenAI } from "@langchain/openai";

const agent = new AgentID();
const handler = new AgentIDCallbackHandler(agent, {
  system_id: process.env.AGENTID_SYSTEM_ID!,
  expected_languages: ["en"],
});

const model = new ChatOpenAI({ model: "gpt-4o-mini" });
const answer = await model.invoke("What is the capital of the Czech Republic?", {
  callbacks: [handler],
});

The handler guards before the model runs and logs on completion. Blocked prompts throw SecurityBlockError. Override telemetry per invocation with { metadata: { agentid_telemetry: { ... } } }.

Agent workflows

Log tool calls and operational steps as separate events grouped by one workflow run id:

workflow.tsTypeScript
import {
  AgentID,
  createAgentIdCorrelationId,
  createAgentIdTelemetryContext,
  createAgentIdWorkflowTrail,
} from "agentid-sdk";

const agent = new AgentID();
const trail = createAgentIdWorkflowTrail({
  agent,
  system_id: process.env.AGENTID_SYSTEM_ID!,
  telemetry: createAgentIdTelemetryContext({
    workflowRunId: createAgentIdCorrelationId(),
    workflowName: "Invoice follow-up",
  }),
});

await trail.runStep(
  {
    telemetry: createAgentIdTelemetryContext({
      workflowStepName: "lookup_invoice",
      toolName: "finance.invoice_lookup",
      toolTargetType: "invoice",
      eventCategory: "tool",
    }),
  },
  async () => lookupInvoice(),
);

runStep logs started, completed or failed automatically. For a single event use agent.logOperation({ system_id, telemetry, event_category, event_status }). Keep one client_event_id per event; group with workflowRunId.

Transparency badge

agentid-sdk/transparency-badge exports a React component that renders an AI disclosure and logs a transparency_badge_rendered event as evidence that the user saw it:

import { AgentIDTransparencyBadge } from "agentid-sdk/transparency-badge";

<AgentIDTransparencyBadge
  telemetry={{
    systemId: process.env.NEXT_PUBLIC_AGENTID_SYSTEM_ID!,
    ingestUrl: "/api/agentid/transparency-render", // your backend relay; keep the API key server-side
    userId: "customer-123",
  }}
  placement="chat-header"
/>;

Errors

ErrorWhen
SecurityBlockError (reason)A wrapped call or LangChain run was blocked
DependencyError (dependency, reason, status)Ingest failed in fail-closed mode

guard() itself does not throw on a block; it returns allowed: false. Ingest retries 5xx and 429 responses and logs a warning if it cannot store the event. See Errors and rate limits.