Skip to main content

sentinelai-sdk

A control plane for multi-agent AI workflows — tracing, contract enforcement, safe state, and failure replay.

Dashboard: www.agentsentinelai.com/dashboard


Install

pip install sentinelai-sdk

Get an API key: open the dashboard → ⚙️ Settings → Generate Key. Free, no credit card required.


What it does

I want to… Feature
See every agent step — inputs, outputs, latency, token counts Tracing
Block bad data from reaching the next agent Contracts
Replay a failed run from any checkpoint once the bug is fixed Replay
Let concurrent agents write shared state without overwriting each other Shared State

These stack — use one, two, or all four.


Quickstart

import sentinel

sentinel.init(api_key="sk_live_...")

with sentinel.workflow("my-pipeline") as run:
    with run.step("planner", step_type="llm_call") as step:
        step.set_input({"query": "Plan a trip to Tokyo"})
        result = planner_agent(query)
        step.set_output({"plan": result})

    with run.step("researcher", step_type="tool_call") as step:
        step.set_input(result)
        data = researcher_agent(result)
        step.set_output({"findings": data})

Tracing

import sentinel

sentinel.init(api_key="sk_live_...")

with sentinel.workflow("travel-planner") as run:
    with run.step("plan", step_type="llm_call") as step:
        step.set_input({"query": query})
        output = plan_agent(query)
        step.set_output(output)

Option 2 — Patch OpenAI clients (sync)

Every client.chat.completions.create() call becomes a traced step automatically.

import openai, sentinel

sentinel.init(api_key="sk_live_...")
client = openai.OpenAI(api_key="...")
sentinel.patch_openai(client, workflow_name="my-pipeline")

sentinel.set_active_run("run_001", "my-pipeline")
response = client.chat.completions.create(model="gpt-4o", messages=[...])

Option 3 — Patch AsyncOpenAI clients (async)

import openai, sentinel

sentinel.init(api_key="sk_live_...")
client = openai.AsyncOpenAI(api_key="...")
sentinel.patch_openai_async(client, workflow_name="my-pipeline")

async def main():
    sentinel.set_active_run("run_001", "my-pipeline")
    response = await client.chat.completions.create(model="gpt-4o", messages=[...])

Deep instrumentation — for libraries like gpt-researcher that create their own AsyncOpenAI instances internally, patch at the class level:

import openai.resources.chat.completions as _oai_completions
sentinel.patch_openai_async(_oai_completions.AsyncCompletions)
# Now every AsyncOpenAI client anywhere in the process is traced

Option 4 — LangChain callback

from sentinel import LangChainCallback
from langchain_openai import ChatOpenAI

sentinel.init(api_key="sk_live_...")
cb = LangChainCallback(workflow_name="my-pipeline")
llm = ChatOpenAI(model="gpt-4o", callbacks=[cb])

Option 5 — Decorator

@sentinel.trace_step(name="planner", step_type="llm_call", workflow_name="my-pipeline")
def planner(query):
    return llm.invoke(query)

Contracts (handoff validation)

Define what one agent must pass to the next. If the payload fails validation, Sentinel raises ContractViolationError, marks the run as blocked in the dashboard, and saves a checkpoint for replay.

import sentinel
from sentinel import ContractViolationError

sentinel.init(api_key="sk_live_...")

sentinel.register_contract(
    agent="researcher",
    accepts={
        "destination": {"type": "string",  "required": True, "min_length": 1},
        "budget":      {"type": "number",  "required": True, "min": 100},
        "days":        {"type": "number",  "required": True, "min": 1, "max": 30},
    },
)

with sentinel.workflow("travel-planner") as run:
    with run.step("planner", step_type="llm_call") as step:
        plan = planner_agent(query)
        step.set_output(plan)

    # Validate handoff before the next agent runs
    sentinel.handoff(
        from_agent="planner",
        to_agent="researcher",
        payload=plan,
        run_id=run.run_id,
    )

    with run.step("researcher", step_type="tool_call") as step:
        research = researcher_agent(plan)
        step.set_output(research)

Field spec options

{"type": "string",  "required": True, "min_length": 1}
{"type": "number",  "required": True, "min": 0, "max": 100}
{"type": "boolean", "required": True}
{"type": "array",   "required": False}

Shared State

Safe concurrent writes — no silent overwrites when agents run in parallel.

# Read
value, version = sentinel.get_state(run_id, "research_results")

# Write with conflict protection (raises ConflictError if stale)
sentinel.propose_state(run_id, "research_results", new_value, base_version=version)

# Auto-retry on conflict (merge function receives current value)
sentinel.propose_state_with_retry(
    run_id, "research_results",
    lambda cur: {**(cur or {}), "hotels": hotel_list}
)

gpt-researcher example

Full deep instrumentation — every internal LLM call becomes a visible step:

import asyncio, os
import sentinel
from sentinel import ContractViolationError
import openai.resources.chat.completions as _oai_completions

sentinel.init(api_key="sk_live_...")

# Patch at the class level to catch gpt-researcher's internal AsyncOpenAI clients
sentinel.patch_openai_async(_oai_completions.AsyncCompletions)

sentinel.register_contract(
    agent="write_report",
    accepts={
        "source_count": {"type": "number",  "required": True, "min": 1},
        "has_context":  {"type": "boolean", "required": True},
        "query":        {"type": "string",  "required": True, "min_length": 1},
    },
)

async def run_research(query: str) -> str:
    from gpt_researcher import GPTResearcher
    researcher = GPTResearcher(query=query, report_type="research_report", verbose=False)

    with sentinel.workflow("gpt-researcher") as run:
        sentinel.set_active_run(run.run_id, "gpt-researcher")

        with run.step("conduct_research", step_type="tool_call") as step:
            step.set_input({"query": query})
            await researcher.conduct_research()
            sources = researcher.get_source_urls()
            context = researcher.get_research_context()
            step.set_output({"source_count": len(sources), "sources": sources[:5]})

        sentinel.handoff(
            from_agent="conduct_research",
            to_agent="write_report",
            payload={"source_count": len(sources), "has_context": bool(context), "query": query},
            run_id=run.run_id,
        )

        with run.step("write_report", step_type="llm_call") as step:
            step.set_input({"source_count": len(sources), "query": query})
            report = await researcher.write_report()
            step.set_output({"word_count": len(report.split())})

    return report

asyncio.run(run_research("What is the impact of AI agents on software engineering in 2025?"))

Run with DuckDuckGo (no API key needed):

pip install gpt-researcher sentinelai-sdk ddgs
RETRIEVER=duckduckgo OPENAI_API_KEY=sk-... python your_script.py

Each run produces ~5 nested steps in the dashboard:

  • openai/gpt-4.1 — agent selection
  • conduct_research — phase wrapper
  • openai/o4-mini — report generation
  • write_report — phase wrapper
  • openai/gpt-4.1 — TOC / introduction / conclusion

Metadata

Release files for sentinelai-sdk 0.1.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sentinelai-sdk 0.1.6
File Size Uploaded Provenance
sentinelai_sdk-0.1.6.tar.gz 23.2 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for sentinelai-sdk 0.1.6
File Interpreter ABI Platform
sentinelai_sdk-0.1.6-py3-none-any.whl Python 3 none any Details

Total release size: 45.0 kB

Release files / sentinelai_sdk-0.1.6.tar.gz

Download URL sentinelai_sdk-0.1.6.tar.gz
Size 23.2 kB
Tags Source
SHA-256 checksum
How to use checksums
bd9d2f4ef0d9828d867a990f13518cfc3c7ec3ea36eeb6469e7d04d226ee3a57
BLAKE2b-256 checksum
How to use checksums
2967aeabe7dcf4e6c308eca9b515738ed1bb275416181854b00d92af49371be0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.7

Release files / sentinelai_sdk-0.1.6-py3-none-any.whl

Download URL sentinelai_sdk-0.1.6-py3-none-any.whl
Size 21.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7bf047ce4d71310052d93f28ca454d3861c2434b3a645888ff264664916c5c49
BLAKE2b-256 checksum
How to use checksums
e1258ed4f8534f4100c0a0d15c9303a64279651dfd1d5917e118283e5b4212c8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.7

Security for sentinelai-sdk 0.1.6

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page