tulip agents · the control runtime for agents that act
Agents that act. Safe by construction.¶
Tulip is an open-source agentic harness with one hard rule: the model never holds the trigger. The agent decides to act — issue the refund, ship the deploy, change the account — and the action runs only after your policy clears it, in code the model can't reach. Build agents on it, or govern the ones you already run in LangChain, CrewAI, or the OpenAI Agents SDK.
No install — the live workbench runs in your browser with your own model key.
from tulip import Agent, tool
@tool
def search_flights(
origin: str, dest: str, date: str
) -> list[dict]:
"Find flights between two cities."
return flights.search(origin, dest, date)
# A model is a string; a tool is a function.
agent = Agent(
model="anthropic:claude-sonnet-4-6",
tools=[search_flights],
system_prompt="You are a travel agent.",
)
print(agent.run_sync(
"Cheapest flight Lisbon to Berlin Friday?"
).text)
Control in the core¶
A model can be brilliant and still be talked into the wrong action. That's a control problem, not an intelligence problem — so Tulip puts the control in code the model can't reach:
- The router picks which shape runs — deterministically. The model classifies the task; it never authors the topology.
- GSAR scores every claim against typed evidence — below threshold the agent regenerates or abstains, never guesses.
- The admission gate clears every side-effecting call:
admit()allows it, holds it for a human, or denies it — and records the decision either way, on a trail where editing any entry breaksverify().
from tulip.control import (
Action, AuditTrail, ControlPolicy, admit, AdmissionError,
)
policy = ControlPolicy(require_human_for={"production"})
trail = AuditTrail()
async def safe_refund(order_id: str, usd: float):
try: # the gate runs before money moves
return await admit(
Action(name="refund", asset=order_id,
kind="payment", environment="production"),
lambda: payments.refund(order_id, usd),
policy=policy, trail=trail,
)
except AdmissionError:
return "Held for a human — not run."
A prompt rule is advisory — the model can be argued out of it. The gate is structural — the wrong action isn't caught in a filter, it never runs. How this compares to prompt rules and guardrails →
Govern the agents you already run¶
You don't rebuild anything. Wrap a tool once with
tulip-frameworks and drop it back in — same name, same
schema — and every call now goes through the same gate and audit trail:
from tulip.control import Action, AuditTrail
from tulip_frameworks.langchain import gate_langchain_tool
from tulip_frameworks.policy_presets import action_gate_policy
safe_refund = gate_langchain_tool(
refund, # your existing LangChain @tool, unchanged
action=lambda name, a: Action(
name=name, asset=a["order_id"],
kind="payment", environment="production",
),
policy=action_gate_policy(), # production → held for a human
trail=AuditTrail(),
)
Bridges ship for LangChain, LangGraph, CrewAI, the OpenAI Agents SDK, LlamaIndex, and Google ADK.
What you get¶
-
One
Agentclass — tools, memory, RAG, streaming — over vendor-neutral backends. Swap models with a string. -
A plain-language task compiles to the right shape — direct answer, pipeline, fan-out, debate, or a gated action.
-
Sequential, parallel, loop, graph, orchestrator, swarm, handoff, and cross-process A2A — one
Agentclass, one event stream. -
ground_finding()emits a typed result only above the GSAR threshold — else an auditableAbstention, never a guess. -
require_human_forpauses the actions that matter and resumes on a human's decision. Approvals survive restarts. -
Every call, verdict, and approval is a typed, hash-chained event —
verify()fails on any edit. Replay any run.
Build it across any domain¶
Every example is a single self-contained file under examples/ with a
matching docs page.
| You're building… | Start here |
|---|---|
| A support / ops agent that acts | human-in-the-loop approvals · incident response |
| An agent on your own data (RAG) | RAG basics · RAG agents |
| A multi-agent workflow | swarm / war-room · supervisor + critic |
| A task-routed agent | cognitive router · procurement approval |
| A security / AI-safety agent | GSAR grounding · injection guardrails |
Full catalog → Notebooks index · Capabilities matrix · API reference
When Tulip is overkill¶
If your agent only reads and summarizes, you may not need an admission gate yet — the control layer earns its keep the moment an action can cost something.
Start building¶
Get started → Try it live ↗ Why Tulip →
The open-source agentic harness — control the action, prove what it did. Safe by construction. Apache-2.0.