Skip to content

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, …), the SecurityAdapter protocol, 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

Build your own integration · SecurityContext