Integrate Agent Sentinel with LangChain, CrewAI, AutoGen, and other agent frameworks.
Overview
Agent Sentinel provides native integrations with popular agent frameworks, enabling automatic tracking of:
Agent actions and tool calls
LLM invocations
Chain execution
Token usage and costs
Errors and retries
The “Big Three” frameworks are supported:
LangChain: Callback-based integration
CrewAI: Wrapper-based integration
AutoGen: Hook-based integration (NEW!)
AutoGen integration
SentinelInspector
Microsoft’s AutoGen is the leading framework in enterprise environments. Agent Sentinel provides seamless integration using AutoGen’s built-in register_reply hook system.
from autogen import AssistantAgent, UserProxyAgentfrom agent_sentinel.integrations.autogen import SentinelInspector# Create the Sentinel inspectorsentinel = SentinelInspector( run_name="my_autogen_run", enforce_policies=True, # Enable active blocking track_costs=True, # Track LLM costs track_messages=True, # Track message flow)# Create AutoGen agents as normalassistant = AssistantAgent( name="assistant", system_message="You are a helpful AI assistant.", llm_config={ "model": "gpt-4", "api_key": "your-api-key-here" })user_proxy = UserProxyAgent( name="user_proxy", human_input_mode="NEVER", max_consecutive_auto_reply=10,)# Secure the agents with one line eachsentinel.register(assistant)sentinel.register(user_proxy)# Run as normal - Sentinel is now monitoring everythingsentinel.start_run()user_proxy.initiate_chat( assistant, message="What's the weather in San Francisco?")sentinel.end_run()# Get execution summarysummary = sentinel.get_run_summary()print(f"Cost: ${summary['run_cost_usd']:.6f}")print(f"Messages: {summary['message_count']}")print(f"LLM Calls: {summary['llm_call_count']}")
How it works
AutoGen’s architecture is different from LangChain/CrewAI:
Agents communicate via messages: Agents send messages back and forth
Reply chain system: AutoGen uses register_reply() to inject hooks
LLM config: LLMs are configured through llm_config dict
Sentinel leverages this by:
Hooking the reply chain (position 0 = highest priority)
Wrapping LLM generation to track token costs
Monitoring message flow for audit trail
This is simpler than CrewAI because AutoGen has a built-in hook system designed exactly for this purpose!
What’s tracked
The inspector automatically tracks:
Agent-to-agent messages:
Sender and recipient
Message content (preview)
Message count per agent
Timestamp and sequence
LLM calls:
Model name
Token usage (prompt + completion)
Calculated cost
Duration
Policy enforcement:
Authorization checks before replies
Budget validation
Rate limiting
Intervention recording
Run lifecycle
Mark run boundaries for accurate tracking:
sentinel = SentinelInspector(run_name="conversation_1")# Register agentssentinel.register(assistant)sentinel.register(user_proxy)# Mark startsentinel.start_run()try: # Run conversation user_proxy.initiate_chat(assistant, message="Hello") # Mark successful completion sentinel.end_run(outcome="completed")except Exception as e: # Mark failed completion sentinel.end_run(outcome="failed") raise
from agent_sentinel.policy import PolicyEngine# Set strict budgetPolicyEngine.configure(run_budget=0.10) # $0.10 maxsentinel = SentinelInspector( run_name="limited_run", enforce_policies=True # Active blocking enabled)sentinel.register(assistant)sentinel.start_run()try: # This will be blocked if cost exceeds $0.10 user_proxy.initiate_chat( assistant, message="Write a very long essay..." )except BudgetExceededError as e: print(f"BLOCKED: {e}") # The assistant was prevented from replying
Sentinel actively blocks operations that violate policies:
from agent_sentinel import PolicyEngine, BudgetExceededErrorfrom agent_sentinel.integrations.langchain import SentinelCallbackHandlerfrom langchain_openai import ChatOpenAI# Set strict budgetPolicyEngine.configure(run_budget=0.10) # $0.10 maxsentinel_handler = SentinelCallbackHandler( run_name="limited_run", enforce_policies=True # Active blocking (default: True))llm = ChatOpenAI(model="gpt-4", callbacks=[sentinel_handler])try: # LLM call authorization checked BEFORE API call response = llm.invoke("Write a very long essay...") # If current spend + estimated cost > budget, blockedexcept BudgetExceededError as e: print(f"BLOCKED: {e}") # LLM call was prevented # Intervention recorded for dashboard
When blocked:
on_llm_start() runs authorization check
PolicyEngine.check_action() validates budget
If violation, BudgetExceededError is raised
Intervention is recorded (type, reason, cost, inputs)
LLM call never reaches the API
Exception propagates to your code
The same authorization happens for tools via on_tool_start().
Run summary
Get a complete summary after execution:
# After agent completessummary = sentinel_handler.get_run_summary()print(f"Total cost: ${summary['total_cost_usd']:.4f}")print(f"LLM calls: {summary['llm_calls']}")print(f"Tool calls: {summary['tool_calls']}")print(f"Total actions: {summary['total_actions']}")print(f"Errors: {summary['errors']}")# Cost breakdown by action typefor action_type, cost in summary['costs_by_action'].items(): print(f" {action_type}: ${cost:.4f}")
SentinelToolNode wraps a LangGraph tool node so every tool invocation runs through the Sentinel policy engine — including evidence requirements, grounding rules, and structured self-repair feedback when a call is rejected.
Each entry maps a tool name to (callable, guard_kwargs) where guard_kwargs accepts the same metadata as @guarded_action (is_commit, requires, grounding_rules, produces_evidence, risk_level, etc.).
Self-repair on block
When the policy engine rejects a tool call, SentinelToolNode returns a ToolMessage whose content is a structured remediation payload the LLM can read on the next turn:
{ "blocked": true, "reason_code": "MISSING_EVIDENCE", "reason": "issue_refund requires evidence from lookup_order", "retry_guidance": "Call lookup_order(order_id=...) first, then retry issue_refund."}
Most frontier models will read the retry_guidance and self-correct without any prompt-engineering on your side.
Working example
A complete runnable example lives at examples/langgraph_sentinel.py in the public SDK repo — a 3-tool refund workflow that demonstrates evidence requirements, grounding constraints, and self-repair when the agent attempts a commit before the prerequisite lookup.
from agent_sentinel import PolicyEngine, BudgetExceededErrorfrom agent_sentinel.integrations.crewai import SentinelCrew# Set strict budgetPolicyEngine.configure(run_budget=0.50) # $0.50 maxcrew = SentinelCrew( agents=[researcher, writer], tasks=[research_task, writing_task], run_name="limited_run", enforce_policies=True # Active blocking enabled)try: result = crew.kickoff()except BudgetExceededError as e: print(f"BLOCKED: {e}") # Tool or LLM call was prevented from executing # Intervention recorded for dashboard visibility
When a tool or LLM is blocked:
Authorization fails before execution
Intervention is recorded (type, reason, risk level)
BudgetExceededError or PolicyViolationError is raised
Agent execution stops cleanly
Visible in Console → Interventions page
Runaway agent protection
Prevent infinite loops and excessive iterations:
crew = SentinelCrew( agents=[researcher], tasks=[task], run_name="protected_run", max_agent_steps=50, # Stop after 50 steps detect_loops=True, # Detect repetition)# If agent exceeds 50 steps or repeats the same action 5 times:# - PolicyViolationError is raised# - Intervention is recorded# - Execution stops# - Dashboard shows the issue
Loop detection: If an agent repeats the same action 5+ times in a row, a warning is logged and an intervention is recorded.Step limit: If an agent exceeds max_agent_steps, a critical intervention is recorded and execution is blocked.
Wrapping existing crews
Retrofit existing CrewAI crews without rewriting code:
For fine-grained control, wrap individual actions:
from agent_sentinel.integrations.crewai import wrap_crew_actionfrom crewai import Agent, Task@wrap_crew_action(name="web_search", cost_usd=0.02, tags=["search", "external"])def search_web(query: str) -> str: """Search the web for information.""" # Your search logic results = perform_search(query) return results@wrap_crew_action(name="analyze_data", cost_usd=0.01, tags=["analysis"])def analyze_data(data: dict) -> dict: """Analyze data and extract insights.""" # Your analysis logic insights = extract_insights(data) return insights# Use wrapped tools with agentsanalyst = Agent( role="Data Analyst", goal="Analyze data and provide insights", backstory="Expert data analyst", tools=[search_web, analyze_data] # Both tools are tracked)# Each tool execution is logged with:# - Action name (web_search, analyze_data)# - Cost ($0.02, $0.01)# - Duration# - Tags (search, external, analysis)# - Success/failure status
The @wrap_crew_action decorator is a thin wrapper around @guarded_action that adds CrewAI-specific tags and metadata.
Custom framework integration
For frameworks not yet supported, use the low-level @guarded_action decorator:
from agent_sentinel import guarded_actionfrom your_framework import Agent, Taskclass TrackedAgent(Agent): @guarded_action(name="agent_step", cost_usd=0.0) def step(self, task): # Your agent logic result = super().step(task) return result @guarded_action(name="tool_call", cost_usd=0.02) def call_tool(self, tool_name, args): result = super().call_tool(tool_name, args) return result
Combining integrations
Use multiple integrations together:
from agent_sentinel.integrations import instrument_openaifrom agent_sentinel.integrations.langchain import SentinelCallbackHandlerfrom langchain_openai import ChatOpenAI# Instrument OpenAI globallyinstrument_openai()# Use LangChain callback for structured trackinghandler = SentinelCallbackHandler(agent_id="hybrid-agent")llm = ChatOpenAI(model="gpt-4o", callbacks=[handler])# Both instrumentation layers work together:# 1. OpenAI instrumentation tracks raw API calls + costs# 2. LangChain handler tracks chain/agent structure
Best practices
Use framework integrations when available: Framework-specific integrations provide better structure and context than raw @guarded_action decorators.
Set agent_id and run_id: Always provide identifiers for filtering and analysis in the web console.
Review run summaries: Use get_run_summary() to understand cost breakdown and identify expensive operations.
Framework compatibility: Test integrations when upgrading LangChain or CrewAI versions, as internal APIs may change.
Ensure both are configured for accurate cost tracking.
”Duplicate events”
If using both LLM instrumentation and framework callbacks, you may see duplicate LLM call records. This is expected - one from the low-level instrumentation, one from the framework callback. The framework callback provides richer context (chain name, agent reasoning) while the low-level instrumentation provides precise token costs.