API quickstart
This is the developer path. You’re building a custom agent (customer-service bot, internal tool, vertical AI product) and wiring in InPolicy yourself. If you’re deploying for employees, see Deploy for your team instead.
Prerequisites
Section titled “Prerequisites”- A tenant at
app.inpolicy.ai. - A few published policies. If you don’t have any yet, use the Policy Inbox to ingest a policy doc first.
- Node.js 18+.
Step 1 — Get an API key
Section titled “Step 1 — Get an API key”- Sign in at
app.inpolicy.aias a tenant admin. - Go to Settings → API Keys.
- Create a key named “dev”. Copy the plaintext. It’s shown only once.
Step 2 — Install the SDK
Section titled “Step 2 — Install the SDK”npm install @inpolicy/sdkStep 3 — Your first policy-aware response
Section titled “Step 3 — Your first policy-aware response”import { InPolicyClient } from '@inpolicy/sdk';import OpenAI from 'openai';
const ip = new InPolicyClient({ apiKey: process.env.INPOLICY_API_KEY! });const openai = new OpenAI();
async function respond(sessionId: string, userMessage: string) { // 1. Record the user turn and get applicable policies. const turn = await ip.recordTurn({ sessionId, turn: { role: 'user', content: userMessage }, });
// 2. Build the system prompt with the injection block. const systemPrompt = [ 'You are a helpful support agent for Acme Corp.', turn.injectionBlock, ].join('\n\n');
// 3. Call your LLM. const completion = await openai.chat.completions.create({ model: 'gpt-4o', messages: [ { role: 'system', content: systemPrompt }, { role: 'user', content: userMessage }, ], }); const output = completion.choices[0].message.content ?? '';
// 4. Record the assistant turn. (Omit checkOutput for the quickstart.) await ip.recordTurn({ sessionId, turn: { role: 'assistant', content: output }, });
return output;}
// Usage: one session per conversation.const sessionId = crypto.randomUUID();console.log(await respond(sessionId, "I'm 16 — can I buy this?"));Run it:
export INPOLICY_API_KEY=inp_live_...export OPENAI_API_KEY=sk-...tsx quickstart.tsYou should see an output where the LLM actually references the policies you’ve authored. If you have a COPPA-related policy, for instance, the response will apply it.
Step 4 — Handle the diff
Section titled “Step 4 — Handle the diff”recordTurn returns more than injectionBlock. The diff field tells you what changed this turn:
if (turn.diff.newlyApplicable.length > 0) { console.log('[InPolicy]', 'newly active this turn:', turn.diff.newlyApplicable.map(p => `${p.citationRef} (${p.enforcement})`).join(', '));}if (turn.diff.newlyReleased.length > 0) { console.log('[InPolicy]', 'no longer active:', turn.diff.newlyReleased.map(p => p.citationRef).join(', '));}Use this to surface policy changes in your UI (“This conversation now involves a minor, COPPA applies”) or to write your own audit log.
Step 5 — (Optional) Add output checking
Section titled “Step 5 — (Optional) Add output checking”Post-inference check catches cases where the LLM drifted from the policies even with the injection block. It’s opt-in per API key. Enable it in Settings → API Keys → your key → Settings → Post-inference checking → Allowed.
Then:
const assistantTurn = await ip.recordTurn({ sessionId, turn: { role: 'assistant', content: output }, checkOutput: true,});
if (assistantTurn.postInferenceCheck && !assistantTurn.postInferenceCheck.safe) { console.warn('[InPolicy] violations detected:', assistantTurn.postInferenceCheck.violations); // Use assistantTurn.postInferenceCheck.suggestedRedaction if available, // or regenerate with stronger prompting.}Latency for post-inference check runs 500–1500ms. Skip it if your UX can’t absorb that.
Step 6 — (Optional) Gate tool calls
Section titled “Step 6 — (Optional) Gate tool calls”If your agent has the ability to take actions (send email, trigger workflows, write to DBs), gate those actions too. Enable tool_call_governance on the API key first.
// Before calling your email-sending tool:const check = await ip.checkToolCall({ sessionId, toolName: 'send_email', arguments: { to: 'competitor@acme.com', subject: 'Q3 roadmap' },});
if (!check.allow) { // Don't execute. Tell the user what policy would be violated. return `Can't send that — ${check.violations[0].explanation}`;}
// Proceed with the tool call.await sendEmail(arguments);- API reference — every endpoint, every field.
- SDK — full
@inpolicy/sdkusage. - LangChain — drop-in integration if you’re building on LangChain.js.
- Privacy — what we store, what we don’t.