Integrations¶
An integration connects a Tulip agent to a system it acts on — messaging (Slack), identity (Okta, Auth0, Entra), compute, and security operations (Splunk log search, CrowdStrike endpoint control, and more). The security catalog was built and hardened first; the pattern is general. Some integrations only read evidence (search logs, look up a reputation, pull cloud posture); the higher-stakes ones let the agent act — contain a host, disable an account. Tulip treats those two very differently.
Tulip follows a core + community split:
tulip-agents(core) ships the agent engine, the admission gate (admit()/approve()/ the tamper-evident audit trail), the grounding contracts (Evidence/ground_finding), the domain ports (LogSource,EndpointSource,IdentitySource, …), theSecurityAdapterprotocol, and bundled offline reference adapters so the SDK runs standalone with no credentials.tulip-integrations(community) ships the maintained, vendor-specific integrations. It depends on core (one-way — core never imports it).
Reads are evidence; writes are governed¶
This is the point of integrating through Tulip rather than handing an agent a
raw vendor SDK. A read returns evidence, and a finding only ships if it clears
GSAR grounding — Tulip's evidence check: a claim must be backed by tool output,
otherwise the agent abstains. A write is a real action, so it doesn't run on the model's
say-so — it runs through the admission chain policy → approval → admission →
audit. You wrap the side effect in an Action; the gate runs it only if a
ControlPolicy (blast radius, verification
score, require_human_for={"production"}) allows — otherwise it raises
AdmissionError. Wire an AuditTrail into admit() and every decision (run or
held) is recorded to its hash chain:
from tulip.control import Action, ControlPolicy, AuditTrail, admit, AdmissionError
# A write is an Action + the call that performs it. Under the default policy a
# production action is HELD for a human — so this raises AdmissionError instead
# of running; pass a trail and the decision is recorded either way.
trail = AuditTrail()
contain = Action(name="endpoint.isolate", asset="prod-db-01", blast_radius=50,
environment="production", kind="containment")
await admit(contain, lambda: ctx.endpoint.isolate("prod-db-01"),
policy=ControlPolicy(), trail=trail)
# → AdmissionError: REQUIRE_HUMAN — a prompt injection can't make this run on its own.
An injected prompt can change what the model decides, but it can't make the
action run — that's the policy's call, not the model's. (ctx.actions.execute
runs the same gate.) The integrations that actually take action (writes):
CrowdStrike (contain a host), Okta / Auth0 / Entra ID (disable an
account), Cortex XSOAR (close an incident), and Slack (post to a
channel). The rest are read-only evidence sources.
Two ways to use an integration¶
1. As a domain provider (recommended) — inject it into a
SecurityContext and your investigation code
stays vendor-agnostic. Swap Okta for Auth0 by changing one line:
import asyncio
from tulip.security import SecurityContext
from tulip_integrations.identity.auth0 import Auth0Identity
from tulip_integrations.threat_intel.virustotal import VirusTotalIntel
async def main():
ctx = SecurityContext(identity=Auth0Identity(), threat_intel=VirusTotalIntel())
await ctx.identity.get_user("[email protected]") # read: hits the real Auth0 Management API
# a write (ctx.identity.disable) goes through ctx.actions.execute — gated
# (disable is a simulated offline stub today; risk reads are offline-sample-only)
asyncio.run(main())
2. As agent tools — merge a vendor's @tools into the toolset for an
autonomous agent:
from tulip.agent import Agent
from tulip.security import security_toolset
from tulip_integrations.siem.splunk import splunk_siem_tool
agent = Agent(
model="anthropic:claude-sonnet-4-6",
tools=security_toolset(siem=False, extra=[splunk_siem_tool]),
system_prompt="You are a SOC analyst. Cite the evidence behind every verdict.",
)
Either way, the same two rules hold: a finding routes through GSAR
ground_finding so an ungrounded result abstains, and a write routes through
the admission gate so it only runs gated and audited — never on best
intentions. (All integrations bring their own credentials from the environment
and return JSON.)
Governed MCP — hand the capability, not the authority¶
Tulip ships an MCP server, so you
can expose a tool to another agent — a Claude or GPT client, a separate
orchestrator — over the Model Context Protocol. What makes this safe: the
admission gate lives inside the action, not the transport. Build the tool so
its body routes the write through admit() / ctx.actions.execute, and a remote
agent gets the capability to ask without the authority to skip your
ControlPolicy — the write still clears policy (and, in production, a human) and
still lands in your audit trail.
What each integration does¶
General-purpose systems first — messaging, identity, compute — then the security-operations block. Domain shorthand: SIEM — log search platforms like Splunk; EDR — endpoint control tools like CrowdStrike; AI-SPM — AI Security Posture Management.
| Integration | Domain | What it does | Provider | Install |
|---|---|---|---|---|
| Slack | notify | Post a finding / message to a channel (write — human handoff; live-only) | (tools) | notify-slack |
| Okta | identity | Look up a user (live), sign-ins (live), risk (offline sample), disable an account (write — simulated offline stub) | OktaIdentity |
identity-okta |
| Auth0 | identity | Look up a user (live), sign-ins (live), risk (offline sample), disable an account (write — simulated offline stub) | Auth0Identity |
identity-auth0 |
| Microsoft Entra ID | identity | User + sign-ins (live), risk + impossible-travel → grounded finding (offline sample), disable an account (write — simulated offline stub) | EntraIdentity |
identity-entra |
| RunPod / Lambda | compute (advanced) | Specialized: deploy a GPU endpoint to fingerprint-probe a model you operate | (probe) | compute-runpod / compute-lambda |
| AWS | cloud | Read-only cloud-posture evidence (in core) | (core) | tulip-agents[aws] |
| Splunk | SIEM | Search logs/events with an SPL query | SplunkLogs |
siem-splunk |
| CrowdStrike Falcon | EDR | Host device record + open detections (offline sample is a fuller forensic timeline), network-contain a host (write) | CrowdStrikeEndpoint |
edr-crowdstrike |
| Cortex XSOAR | SOAR | Read incidents, search, close an incident (write) + ground incidents to findings | CortexXSOAR |
soar-cortex-xsoar |
| VirusTotal | threat-intel | Reputation for an IP, domain, or file hash | VirusTotalIntel |
threat-intel-virustotal |
| Wiz | AI-SPM | AI-BOM inventory + posture issues → grounded findings | (tools) | wiz-aispm |
| OSV | supply-chain | Dependency vulnerability lookup (in core) | (core) | built-in |