DOCUMENTATION
Sentinely Docs
Everything you need to protect your AI agents from prompt injection, memory poisoning, and drift.
Quick Start
Protect your AI agent in 3 lines of code. No configuration required to get started.
Install the package
pip install sentinely
Wrap your agent
from sentinely import protect
# Wrap any AI agent in one line
agent = protect(
your_agent,
task="Summarize quarterly reports"
)Add your API key
# .env
SENTINELY_API_KEY=sntnl_live_...THAT'S IT
Your agent is now protected. Sentinely monitors every action, blocks attacks automatically, and streams events to your dashboard in real time. No additional code required.
Installation
Python 3.10+ or Node.js 18+.
pip install sentinely
Configuration
Sentinely is configured via environment variables. Create a .env file in your project root.
# Required — get this from your dashboard
SENTINELY_API_KEY=sntnl_live_...
# Optional — defaults shown
SENTINELY_ENV=production| VARIABLE | REQUIRED | DEFAULT | DESCRIPTION |
|---|---|---|---|
SENTINELY_API_KEY | Yes | — | Your API key. Sign up free at sentinely.ai/signup. |
SENTINELY_ENV | No | development | Set to production to enable event forwarding. |
Never commit your SENTINELY_API_KEY to version control. Add .env to your .gitignore file.
protect()
The single entry-point for all Sentinely protection. Returns a ProtectedAgent that wraps your agent.
from sentinely import protect
protected = protect(
agent, # Any agent object
task, # str — the agent's mission / system prompt
policy="strict", # "strict" | "monitor" | "permissive"
agent_id=None, # Optional str — stable ID across restarts
org_id=None, # Optional str — your organisation slug
tracker=None, # Optional MultiAgentTracker
)PARAMETERS
| PARAMETER | TYPE | REQUIRED | DESCRIPTION |
|---|---|---|---|
agent | object | Yes | Any agent that exposes .run(), .invoke(), .ainvoke(), or __call__(). |
task | str | Yes | The agent's purpose / system prompt. Used as the baseline for drift detection. |
policy | str | No | "strict" blocks dangerous actions. "monitor" logs only. "permissive" allows with warnings. |
agent_id | str | No | Stable identifier. Defaults to a random hex ID. Use a fixed value to correlate sessions. |
org_id | str | No | Organisation slug. Defaults to "local". Visible in the dashboard under your org. |
tracker | MultiAgentTracker | No | Pass a tracker to enable inter-agent drift monitoring across agent boundaries. |
RETURNS
A ProtectedAgent instance that is a transparent proxy to your original agent. It exposes the same interface:
.invoke(input)Async: scan input → run agent → return result.ainvoke(input)Async version of .invoke().run(input)Sync wrapper. Runs the async pipeline via event loop.__call__(input)Callable shorthand. Delegates to .invoke().score_action(tool, params)Score a pending tool call. Call from your tool hooks.memoryAccess the MemoryFirewall for poisoning detection.get_audit_log()Return all events buffered locally this sessionEXAMPLE
import asyncio
from sentinely import protect
agent = protect(
my_agent,
task="Analyse customer churn data. Read-only. No external API calls.",
policy="strict",
agent_id="churn-analyst-v2",
)
# Synchronous
result = agent.run("Analyse churn for Q3")
# Async
result = await agent.ainvoke("Analyse churn for Q3")
# As callable
result = agent("Analyse churn for Q3")COMING SOON
Native Python adapters for CrewAI, AutoGen and LlamaIndex. Sentinely will plug directly into your existing agent framework with zero code changes.
Policy Modes
Choose the enforcement level that matches your deployment stage. You can change the policy at any time without restarting.
Blocks any action that scores above the risk threshold. Raises SentinelyBlockedError so you can handle it gracefully. Recommended for production.
policy="strict"Logs and scores every action but never blocks execution. Use during development or when rolling out Sentinely to an existing agent without changing its behaviour.
policy="monitor"Allows all actions but attaches risk scores and reasons to each event. Useful for research, red-teaming, or building a baseline before switching to strict.
policy="permissive"HANDLING BLOCKS
from sentinely.exceptions import SentinelyBlockedError
try:
result = agent.run(user_input)
except SentinelyBlockedError as e:
print(f"Blocked: {e.reason}")
print(f"Risk score: {e.risk_score}")
print(f"Attack type: {e.attack_type}")
# Return a safe fallback response to the userFramework Examples
Sentinely works with any Python or Node.js AI agent framework. Select your framework below.
from openai import OpenAI
from sentinely import protect
client = OpenAI()
class MyAgent:
def run(self, prompt):
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}]
)
return response.choices[0].message.content
agent = MyAgent()
agent = protect(
agent,
task="Answer customer support questions about billing",
policy="strict",
agent_id="openai-support-agent"
)
result = agent.run("How do I update my payment method?")LangChain Integration
Sentinely integrates natively with LangChain. Choose the approach that fits your architecture.
INSTALLATION
pip install sentinely[langchain]
THREE APPROACHES
Wrap individual tools. Blocked calls return a safe string instead of throwing. Great for graceful degradation.
Attach to any LangChain agent executor. Throws SentinelyBlockedError on block, halting the agent.
One-liner convenience wrapper. Mirrors the Python protect_langchain() API. Installs the callback and returns the agent.
CODE EXAMPLES
from sentinely import protect
from sentinely.adapters.langchain import (
SentinelyTool, SentinelyCallbackHandler, protect_langchain,
)
# Option 1 — Tool wrapper (per-tool protection)
agent = protect(my_agent, task="Summarise quarterly reports", policy="strict")
safe_tool = SentinelyTool(your_tool, agent)
# Option 2 — Agent-wide callback
agent = protect(my_agent, task="Summarise quarterly reports", policy="strict", agent_id="my-agent")
handler = SentinelyCallbackHandler(agent)
executor = AgentExecutor(agent=..., tools=tools, callbacks=[handler])
# Option 3 — Convenience wrapper (recommended)
executor = protect_langchain(
AgentExecutor(agent=..., tools=tools),
task="Summarise quarterly reports",
policy="strict",
agent_id="my-agent",
)LangChain is an optional dependency. Python: pip install sentinely[langchain] installs the extras. Node.js: install langchain and @langchain/core separately. They are peer dependencies.
Multi-Agent Tracking
Track behavioral drift across every agent in a pipeline. Detect inter-agent manipulation before it spreads.
WHAT IT DETECTS
Messages that slowly expand an agent's permissions or role beyond what was originally authorised.
Instructions that attempt to redefine the agent's identity, persona, or core behavioral constraints.
Many individually low-risk messages that together shift the agent's behavior significantly over time.
Requests for capabilities, access, or actions that fall outside the agent's original task scope.
CODE EXAMPLE
import asyncio
from sentinely import protect, MultiAgentTracker
from sentinely.multi_agent import AgentMessage
tracker = MultiAgentTracker()
# Register each agent (async)
await tracker.register_agent(
agent_id='agent-1',
session_id='session-abc',
system_prompt='Summarise financial reports',
)
await tracker.register_agent(
agent_id='agent-2',
session_id='session-abc',
system_prompt='Send email summaries',
)
# Pass tracker into protect()
agent1 = protect(
my_agent1,
task='Summarise financial reports',
agent_id='agent-1',
tracker=tracker,
)
# Check drift scores (synchronous)
scores = tracker.get_all_drift_scores()
# {'agent-1': {'drift_score': 0, 'risk_level': 'stable'}}DRIFT RISK LEVELS
Python: drift_score < 20
Node: driftScore < 20
Agent is behaving within its original constraints. No action required.
Python: 20 ≤ drift_score < 40
Node: 20 ≤ driftScore < 40
Suspicious patterns detected. Review recent inter-agent messages in the dashboard.
Python: 40 ≤ drift_score < 60
Node: 40 ≤ driftScore < 60
Significant drift detected. Monitor closely and consider pausing the agent for review.
Python: drift_score ≥ 60
Node: driftScore ≥ 60
Agent is compromised. All further messages to this agent are blocked. Reset the fingerprint to resume.
Manipulation events appear in the dashboard with attack_type: 'manipulation'. Python field names use snake_case (drift_score, risk_level). Node.js uses camelCase (driftScore, riskLevel).
Understanding Alerts
Every action your agent takes gets a risk score from 0–100. Here is how to read what Sentinely is telling you.
RISK SCORE
Action is within normal operating bounds. Agent is behaving as expected.
Action looks suspicious. Logged and surfaced in your dashboard. Agent continues but you should review.
Action is blocked. Agent receives an error. Slack/email alerts fire. Item appears in Quarantine if memory-related.
ATTACK TYPES
Malicious instructions embedded in external content trying to hijack the agent's behavior. Most common attack vector.
Attempts to write malicious instructions into the agent's long-term memory to influence future sessions.
Agent's actions gradually deviate from its original task. Often a sign of a slow multi-step manipulation.
One agent attempts to manipulate another in a multi-agent pipeline. Detected by behavioral fingerprinting.
DRIFT SCORE
Framework Guides
Complete, copy-pasteable integration examples for popular AI agent frameworks.
LANGCHAIN (PYTHON)
Wrap a LangChain agent with tool calling. Sentinely monitors every tool invocation.
pip install sentinely[langchain] langchain langchain-openaifrom langchain_openai import ChatOpenAI
from langchain.agents import AgentExecutor, create_openai_tools_agent
from langchain_core.tools import tool
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from sentinely.adapters.langchain import protect_langchain
@tool
def lookup_order(order_id: str) -> str:
"""Look up an order by ID and return its status."""
return f"Order {order_id}: shipped, arriving Thursday"
@tool
def send_email(to: str, subject: str, body: str) -> str:
"""Send an email to a customer."""
return f"Email sent to {to}"
llm = ChatOpenAI(model="gpt-4o", temperature=0)
prompt = ChatPromptTemplate.from_messages([
("system", "You are a customer support agent. Help with orders."),
("human", "{input}"),
MessagesPlaceholder("agent_scratchpad"),
])
agent = create_openai_tools_agent(llm, [lookup_order, send_email], prompt)
executor = AgentExecutor(agent=agent, tools=[lookup_order, send_email])
# Wrap with Sentinely — one line
executor = protect_langchain(
executor,
task="Answer customer support questions about orders",
policy="strict",
agent_id="support-agent",
)
result = executor.invoke({"input": "Where is order #1234?"})CREWAI
Add Sentinely to a CrewAI crew with multiple agents. Each agent gets its own behavioral fingerprint.
pip install sentinely crewai crewai-toolsfrom crewai import Agent, Task, Crew
from sentinely import protect
researcher = Agent(
role="Senior Research Analyst",
goal="Find and summarize market trends",
backstory="You are an expert market researcher.",
verbose=True,
)
writer = Agent(
role="Technical Writer",
goal="Write clear reports from research findings",
backstory="You write concise, accurate technical reports.",
verbose=True,
)
# Wrap each agent independently
researcher = protect(
researcher,
task="Research market trends from public data only",
policy="strict",
agent_id="crewai-researcher",
)
writer = protect(
writer,
task="Write reports from provided research. No external access.",
policy="strict",
agent_id="crewai-writer",
)
research_task = Task(
description="Analyze Q1 2026 AI infrastructure trends",
expected_output="A bullet-point summary of top 5 trends",
agent=researcher,
)
write_task = Task(
description="Write a 1-page report from the research summary",
expected_output="A polished report in markdown",
agent=writer,
)
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, write_task],
verbose=True,
)
result = crew.kickoff()VERCEL AI SDK (NODE.JS)
Protect a Vercel AI SDK route handler. Sentinely runs as middleware on every streamed response.
npm install sentinely ai @ai-sdk/openai// app/api/chat/route.ts
import { streamText } from 'ai'
import { openai } from '@ai-sdk/openai'
import { sentinelyMiddleware } from 'sentinely/adapters/vercel'
export async function POST(req: Request) {
const { messages } = await req.json()
const result = streamText({
model: openai('gpt-4o'),
system: 'You are a helpful assistant for our SaaS product.',
messages,
experimental_transform: sentinelyMiddleware({
task: 'Answer product questions. No competitor comparisons.',
policy: 'strict',
agentId: 'vercel-chat-agent',
}).transform(),
})
return result.toDataStreamResponse()
}OPENAI AGENTS SDK (PYTHON)
Wrap an OpenAI Agents SDK agent. Sentinely intercepts tool calls and function outputs.
pip install sentinely openai-agentsfrom agents import Agent, Runner, function_tool
from sentinely import protect
@function_tool
def get_weather(city: str) -> str:
"""Get the current weather for a city."""
return f"72°F and sunny in {city}"
@function_tool
def book_flight(origin: str, dest: str, date: str) -> str:
"""Book a flight between two cities."""
return f"Flight booked: {origin} → {dest} on {date}"
agent = Agent(
name="travel-assistant",
instructions="You help users plan trips. Only book flights "
"the user explicitly requests.",
tools=[get_weather, book_flight],
)
# Wrap with Sentinely
agent = protect(
agent,
task="Help users plan trips. Only book when explicitly asked.",
policy="strict",
agent_id="openai-travel-agent",
)
result = Runner.run_sync(agent, "What's the weather in Tokyo?")RAW PYTHON
The minimal example. Works with any Python object that has a callable method.
pip install sentinelyfrom sentinely import protect
class MyAgent:
def run(self, prompt: str) -> str:
# Your agent logic — call an LLM, run tools, etc.
return f"Processed: {prompt}"
agent = MyAgent()
# Wrap with Sentinely
agent = protect(
agent,
task="Summarize customer feedback. Read-only, no external calls.",
policy="strict",
agent_id="feedback-summarizer",
)
# Use as normal — Sentinely monitors .run(), .invoke(), .__call__()
result = agent.run("Summarize last week's support tickets")RAW NODE.JS
Same minimal pattern for Node.js. Wraps any object or function.
npm install sentinelyimport { protect } from 'sentinely'
class MyAgent {
async run(prompt) {
// Your agent logic — call an LLM, run tools, etc.
return `Processed: ${prompt}`
}
}
const agent = protect(new MyAgent(), {
task: 'Summarize customer feedback. Read-only, no external calls.',
policy: 'strict',
agentId: 'feedback-summarizer',
})
// Use as normal — Sentinely monitors .run(), .invoke(), .call()
const result = await agent.run('Summarize last week\'s support tickets')CI/CD Security Scanner
Scan your agent system prompts for vulnerabilities before they reach production. The Sentinely CLI finds prompts in your source code and scores them automatically. It ships inside the sentinely npm package, no separate install needed.
Quick Start
npx sentinely scan ./src --api-key $SENTINELY_API_KEYOptions
CI/CD Examples
GitHub Actions
name: Agent Security Scan
on: [pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Sentinely Security Scan
run: npx sentinely scan ./src --api-key ${{ secrets.SENTINELY_API_KEY }} --format githubGitLab CI
sentinely-scan:
script:
- npx sentinely scan ./src --api-key $SENTINELY_API_KEYAny CI system
npx sentinely scan ./src --api-key $SENTINELY_API_KEYConfig File
# .sentinely.yml
threshold: 70
fail_on: high
include:
- "src/**/*.py"
- "src/**/*.ts"
exclude:
- "tests/**"No signup needed for up to 3 scans per day. Create a free account at sentinely.ai for unlimited scans.
Supply Chain Monitor
Detect when external tools change their response schemas, spike in latency, or start returning errors. Sentinely builds a behavioral baseline for each tool and alerts on deviations.
After each external tool call, report the response back to Sentinely. The first 20 calls build a baseline (schema shape, latency distribution, error rate). After locking, any deviation triggers an anomaly alert in the dashboard.
# After calling an external tool:
result = await external_api.call(params)
agent.report_tool_response(
tool_name="lookup_user",
response_data=result,
latency_ms=elapsed_ms,
is_error=False,
)View tool health and anomalies in the dashboard at /tools. Anomalies include schema changes (new/removed fields), latency spikes (>3x p95), and error spikes.
Threat Intelligence
When you confirm an attack in the dashboard, the attack pattern is anonymized and shared across all Sentinely customers. Your agents benefit from attacks detected at other organizations without exposing any private data.
How it works: Label any alert as “Confirmed Attack” in the dashboard. Sentinely extracts the attack pattern, strips all org-specific data (emails, URLs, agent IDs), and adds it to the shared signature database.
SDK integration: The SignatureCache refreshes every 6 hours automatically. No code changes needed. New patterns are applied to scoring immediately.
Dashboard: The overview page shows active signature count. Alerts matched by collective intelligence display a “Detected by Collective Intelligence” badge.
Red Team
Automated adversarial testing. Generates tailored attack vectors against your agent's system prompt and scores each one through the Sentinely pipeline. Runs against the scoring engine, not your live agent. Safe to run anytime.
Click Run Now in the dashboard at /redteam. Sentinely generates 30+ static attack templates (injection, drift, memory poisoning, escalation, multi-agent) plus LLM-adaptive payloads tailored to your specific system prompt.
Each attack vector is scored through the full pipeline. The report shows detected vs bypassed vectors with actionable remediation for each bypass.
Schedule weekly runs to continuously test your defenses as your prompts evolve. Available on all plans (free: 1/month, starter: 4/month, pro+: unlimited).
Behavioral DNA
Builds a unique behavioral profile for each agent: tool call sequences, parameter patterns, and active hours. After the baseline locks, any deviation from the established DNA triggers drift detection.
No code changes needed. The SDK automatically tracks 2-gram tool sequences, parameter distributions (file paths, email domains, URL patterns), and hourly UTC activity. DNA locks after 100+ actions across 5+ sessions over 7+ days.
Once locked, a deviation score (0-100) is computed for each action: novel tool sequences (+30), unknown parameter targets (+20-25), unusual hours (+15). High deviations generate drift events in the timeline.
View the DNA profile in the Behavioral DNA tab in the agent detail view at /agents.
Certification
Issue verifiable security certifications for agents that pass continuous monitoring. Each cert includes a public verification URL and an embeddable badge.
Criteria: 30+ days monitored, no critical alerts in 30 days, quarantine clear, scan score ≥ 70, red team score ≥ 80. Certifications are valid for 30 days and auto-revoke if criteria are no longer met.
Issue and manage certifications at /certifications. Each cert includes a public URL at sentinely.ai/cert/[token] that anyone can visit to verify the agent’s security status.
Available on paid plans only (starter: 1 active cert, pro+: unlimited).
FAQ
Common questions about Sentinely.