Integrations¶
An integration lets a Tulip agent reach a real tool — and, where it can take action, do so on your terms. Today's integrations are the security domain (SIEM, EDR, identity), built and hardened first. Some 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. 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:
from tulip.security import SecurityContext
from tulip_integrations.identity.auth0 import Auth0Identity
from tulip_integrations.threat_intel.virustotal import VirusTotalIntel
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)
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¶
Action integrations first (they write), then read-only evidence sources:
| Integration | Domain | What it does | Provider | Install |
|---|---|---|---|---|
| CrowdStrike Falcon | EDR | Host device record + open detections (offline sample is a fuller forensic timeline), network-contain a host (write) | CrowdStrikeEndpoint |
edr-crowdstrike |
| 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 |
| Cortex XSOAR | SOAR | Read incidents, search, close an incident (write) + ground incidents to findings | CortexXSOAR |
soar-cortex-xsoar |
| Splunk | SIEM | Search logs/events with an SPL query | SplunkLogs |
siem-splunk |
| 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) | vuln-wiz |
| Slack | notify | Post a finding / message to a channel (write — human handoff; live-only) | (tools) | notify-slack |
| AWS | cloud | Read-only cloud-posture evidence (in core) | (core) | tulip-agents[aws] |
| OSV | supply-chain | Dependency vulnerability lookup (in core) | (core) | built-in |
| RunPod / Lambda | compute (advanced) | Specialized: deploy a GPU endpoint to fingerprint-probe a model you operate | (probe) | compute-runpod / compute-lambda |