Skip to content

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.

  • 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+.
  1. Sign in at app.inpolicy.ai as a tenant admin.
  2. Go to Settings → API Keys.
  3. Create a key named “dev”. Copy the plaintext. It’s shown only once.
Terminal window
npm install @inpolicy/sdk

Step 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:

Terminal window
export INPOLICY_API_KEY=inp_live_...
export OPENAI_API_KEY=sk-...
tsx quickstart.ts

You 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.

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.

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.

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/sdk usage.
  • LangChain — drop-in integration if you’re building on LangChain.js.
  • Privacy — what we store, what we don’t.