Skip to main content

Control and coordination infrastructure for AI agents

Project description

Splinter

Control and coordination infrastructure for multi-agent AI systems.

pip install splinter
from splinter import Splinter

s = Splinter(openai_key="sk-...", max_budget=5.0)
result = await s.run("agent", "Do the task")
# Automatically stops at $5 - no runaway costs

No Docker. No config files. Just pip install and go.


๐Ÿ“‹ Quick Reference

All objects, organized by layer. Local = free, Cloud = paid.

Core

Object What it does
Splinter Simple API - create and run agents in one line
Workflow Run multiple agents with dependencies
Agent Single AI entity with config
AgentConfig Configuration for an agent

๐Ÿ›ก๏ธ Control Layer (Local)

Object What it does
ExecutionLimits Budget ($), step count, time limits
LoopDetectionConfig Catch infinite loops
ToolAccessController Which agent can use which tools
RateLimiter Max calls per minute per agent/tool
CircuitBreaker Stop after N failures
CircuitBreakerRegistry Manage all breakers, emergency stop
DecisionEnforcer Lock decisions so agents can't flip-flop
RetryStrategy Retry failed calls with backoff
RulesEngine Custom BLOCK/WARN/LOG rules
MemoryStore Capped memory with auto-eviction

๐Ÿค Coordination Layer (Local)

Object What it does
SharedState Single source of truth for all agents
StateOwnership Who can write to which fields
CheckpointManager Save progress, resume after crash
SchemaValidator Validate agent outputs
HandoffManager Validate data between agents
ChainContext Agents see what happened before them
GoalTracker Track progress toward goals
ActionEligibility Which agent can act right now
CompletionTracker Agents must say "I'm done"
WaitTracker Track why agents are idle

โ˜๏ธ Splinter Cloud (Paid)

Feature What it does
Live Control Pause, resume, stop agents remotely
Global Stop Emergency stop all agents instantly
Live Rules Change rules without redeploying
Live Limits Modify budgets/rate limits on the fly
Tool Access Update permissions in real-time
Break Loops Force-break detected loops
Rollback Resume from safe checkpoint
Dashboard Live view of all agents, state, handoffs
Status View See active, waiting, blocked, eligible agents
Deadlock Detection Automatically surface coordination stalls
Bottleneck Analysis Find why agents are waiting

What is Splinter?

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚            YOUR AGENTS                  โ”‚
โ”‚   Agent 1    Agent 2    Agent 3  ...    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                  โ”‚
                  โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚         SPLINTER (Local - Free)         โ”‚
โ”‚                                         โ”‚
โ”‚  ๐Ÿ›ก๏ธ CONTROL         ๐Ÿค COORDINATION     โ”‚
โ”‚  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€       โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€      โ”‚
โ”‚  Budget limits     Shared state         โ”‚
โ”‚  Rate limiting     Checkpointing        โ”‚
โ”‚  Circuit breakers  Schema validation    โ”‚
โ”‚  Decision locks    Goal tracking        โ”‚
โ”‚  Loop detection    Action eligibility   โ”‚
โ”‚                                         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                      โ”‚
          โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
          โ–ผ                       โ–ผ
   OpenAI / Claude         โ˜๏ธ Splinter Cloud
   Gemini / Grok              (Paid API Key)
                              โ”‚
                              โ”œโ”€โ”€ Live Dashboard
                              โ”œโ”€โ”€ Remote Control
                              โ”œโ”€โ”€ Deadlock Detection
                              โ””โ”€โ”€ Bottleneck Analysis

Local (Free) = Control + Coordination. Runs entirely on your machine.

Cloud (Paid) = Live observability + remote control. Add API key to enable.


๐Ÿ“ฆ Installation

pip install splinter

Then install your LLM provider:

pip install openai              # OpenAI
pip install anthropic           # Claude
pip install google-generativeai # Gemini
pip install openai              # Grok (uses OpenAI SDK)

๐Ÿš€ Quick Start

Step 1 โ€” Create with limits

from splinter import Splinter

s = Splinter(
    openai_key="sk-...",
    max_budget=5.0,   # Stop at $5
    max_steps=50,     # Stop after 50 calls
)

Step 2 โ€” Run

result = await s.run("researcher", "Find the top 3 AI trends")

Step 3 โ€” Check spend

print(f"Cost: ${s.cost:.4f} | Steps: {s.steps}")

Done. Your agent is protected.


โ˜๏ธ Splinter Cloud (Paid)

Add an API key to unlock live control and observability.

Connect:

from splinter import Splinter

# Option 1: Pass API key directly
s = Splinter(
    openai_key="sk-...",
    api_key="sk-splinter-...",  # Cloud API key
)

# Option 2: Connect later
s = Splinter(openai_key="sk-...")
await s.connect_cloud(api_key="sk-splinter-...")

# Option 3: Environment variable
# export SPLINTER_API_KEY="sk-splinter-..."
s = Splinter(openai_key="sk-...")  # Auto-connects

What you get:

Feature Description
Live Dashboard See all agents, shared state, ownership, checkpoints, handoffs in real-time
Pause/Resume Pause any agent, resume when ready
Stop Immediately Stop agents without redeploying
Global Stop Emergency stop all agents at once
Change Rules Live Update rules without restart
Change Limits Live Modify budgets, rate limits on the fly
Update Tool Access Change permissions in real-time
Break Loops Force-break detected loops
Rollback Resume from any checkpoint
Status View See which agents are active, waiting, blocked, or eligible
Deadlock Detection Automatically surface coordination stalls
Bottleneck Analysis Understand why agents are waiting

Check connection:

if s.is_cloud_connected:
    print("Connected to Splinter Cloud")

๐Ÿงฑ Core Objects

Splinter โ€” Simple API

The easiest way. Creates everything internally.

from splinter import Splinter

s = Splinter(openai_key="sk-...", max_budget=10.0)
result = await s.run("researcher", "Find AI trends")
print(f"Cost: ${s.cost:.4f}")
Workflow โ€” Multi-agent orchestration

Run multiple agents with dependencies and shared limits.

from splinter.workflow import Workflow
from splinter.types import AgentConfig, ExecutionLimits, LLMProvider

workflow = Workflow(
    workflow_id="pipeline",
    limits=ExecutionLimits(max_budget=20.0),
    checkpoint_enabled=True,
)

workflow.add_agent(AgentConfig(
    agent_id="researcher",
    provider=LLMProvider.OPENAI,
    model="gpt-4o",
    system_prompt="Research topics. Output JSON.",
))

workflow.add_agent(AgentConfig(
    agent_id="writer",
    provider=LLMProvider.OPENAI,
    model="gpt-4o",
    system_prompt="Write articles. Output JSON.",
))

workflow.add_step("researcher")
workflow.add_step("writer", depends_on=["researcher"])

result = await workflow.run(initial_state={"topic": "AI"})
Agent โ€” Single AI entity

Build agents with the fluent API.

from splinter.workflow import AgentBuilder
from splinter.types import LLMProvider

agent = (
    AgentBuilder("researcher")
    .with_provider(LLMProvider.OPENAI, "gpt-4o")
    .with_system_prompt("Research topics. Output JSON.")
    .with_tools(["web_search"])
    .with_state_ownership(["research.*"])
    .build(gateway)
)

result = await agent.run(task="Research AI trends")

๐Ÿ›ก๏ธ Control Objects

Import from splinter.control or splinter.types

ExecutionLimits โ€” Budget, steps, time
from splinter.types import ExecutionLimits

limits = ExecutionLimits(
    max_budget=10.0,       # Stop at $10
    max_steps=100,         # Stop after 100 calls
    max_time_seconds=600,  # Stop after 10 min
)

Use with Workflow:

workflow = Workflow(workflow_id="x", limits=limits)
LoopDetectionConfig โ€” Break infinite loops
from splinter.types import LoopDetectionConfig

config = LoopDetectionConfig(
    max_repeated_outputs=3,  # Same output 3x = loop
    max_no_state_change=5,   # No change 5x = loop
)

workflow = Workflow(workflow_id="x", loop_detection=config)
# Raises LoopDetectedError when stuck
ToolAccessController โ€” Per-agent permissions
from splinter.control import ToolAccessController

ctrl = ToolAccessController()
ctrl.set_allowed_tools("researcher", ["web_search", "read_file"])
ctrl.set_allowed_tools("writer", ["write_file"])

ctrl.check_access("researcher", "web_search")   # โœ“
ctrl.check_access("researcher", "delete_file")  # โœ— ToolAccessDeniedError
RateLimiter โ€” Calls per minute
from splinter.control import RateLimiter

limiter = RateLimiter()
limiter.set_agent_limit("researcher", calls=10, window_seconds=60)
limiter.set_tool_limit("web_search", calls=20, window_seconds=60)

limiter.check_agent("researcher")        # Raises if over limit
limiter.record_agent_call("researcher")  # Record the call
CircuitBreaker โ€” Stop on failures
from splinter.control import CircuitBreaker, CircuitBreakerConfig

breaker = CircuitBreaker(
    breaker_id="openai",
    config=CircuitBreakerConfig(
        failure_threshold=5,  # Open after 5 fails
        timeout_seconds=60,   # Retry after 60s
    )
)

breaker.check()  # Raises CircuitOpenError if open

try:
    result = await call()
    breaker.record_success()
except:
    breaker.record_failure()

Global emergency stop:

from splinter.control import CircuitBreakerRegistry

registry = CircuitBreakerRegistry()
registry.register("openai", config)
registry.register("anthropic", config)
registry.trip_all("Emergency!")  # Stop everything
DecisionEnforcer โ€” Lock decisions
from splinter.control import DecisionEnforcer, DecisionType

enforcer = DecisionEnforcer(auto_lock=True)

enforcer.record_decision(
    decision_id="strategy",
    agent_id="planner",
    decision_type=DecisionType.STRATEGY,
    value="parallel",
)

# Can't change now!
enforcer.record_decision(
    decision_id="strategy",
    agent_id="planner",
    decision_type=DecisionType.STRATEGY,
    value="sequential",  # Raises DecisionLockError
)
RetryStrategy โ€” Retry with backoff
from splinter.control import RetryStrategy, RetryConfig, RetryMode

strategy = RetryStrategy(RetryConfig(
    max_attempts=3,
    initial_delay=1.0,
    max_delay=30.0,
    backoff_multiplier=2.0,
    mode=RetryMode.BASIC,  # or FAIL_CLOSED
))

result = await strategy.execute(unreliable_fn, arg1, arg2)
RulesEngine โ€” Custom rules
from splinter.control import RulesEngine, Rule, RuleAction

engine = RulesEngine()

engine.add_rule(Rule(
    rule_id="block_expensive",
    condition=lambda ctx: ctx.get("cost", 0) > 10,
    action=RuleAction.BLOCK,
    message="Cost > $10",
))

engine.add_rule(Rule(
    rule_id="warn_delete",
    condition=lambda ctx: ctx.get("tool") == "delete_file",
    action=RuleAction.WARN,
    message="Deleting files",
))

engine.evaluate({"cost": 15})  # Raises RuleViolationError
MemoryStore โ€” Capped storage
from splinter.control import MemoryStore

store = MemoryStore(
    max_size_bytes=10*1024*1024,  # 10 MB
    max_entries=1000,
)

store.set("researcher", "key", "value")
value = store.get("researcher", "key")
# Auto-evicts old entries when full

๐Ÿค Coordination Objects

Import from splinter.coordination

SharedState โ€” Single source of truth
from splinter.coordination import SharedState

state = SharedState(initial_data={"topic": "AI"})

state.set("research.findings", ["a", "b", "c"])
findings = state.get("research.findings")

print(state.version)  # Increments on change

# Snapshot & restore
snapshot = state.snapshot()
state.set("oops", "mistake")
state.restore(snapshot)  # Rolled back
StateOwnership โ€” Who writes what
from splinter.coordination import StateOwnership

ownership = StateOwnership()
ownership.register_ownership("researcher", ["research.*"])
ownership.register_ownership("writer", ["content.*"])

ownership.check_write_permission("researcher", "research.x")  # โœ“
ownership.check_write_permission("researcher", "content.x")   # โœ—
CheckpointManager โ€” Save & resume
from splinter.coordination import CheckpointManager, FileCheckpointStorage

mgr = CheckpointManager(storage=FileCheckpointStorage("./checkpoints"))

# Save
mgr.create_checkpoint(
    workflow_id="wf-1",
    step=3,
    agent_id="researcher",
    status=AgentStatus.COMPLETED,
    state=state,
    metrics=metrics,
)

# Resume after crash
cp = mgr.get_latest_checkpoint("wf-1")
resume_from = cp.state
SchemaValidator โ€” Validate outputs
from splinter.coordination import SchemaValidator

validator = SchemaValidator()

schema = {
    "type": "object",
    "properties": {"findings": {"type": "array"}},
    "required": ["findings"],
}

validator.validate(output, schema)  # Raises SchemaValidationError
HandoffManager โ€” Agent-to-agent validation
from splinter.coordination import HandoffManager

handoff = HandoffManager(mode="strict")
handoff.register_schema("researcher", "writer", schema)
handoff.validate_handoff("researcher", "writer", data)
ChainContext โ€” Execution history
from splinter.coordination import ChainContext

ctx = ChainContext()
ctx.register_agent("researcher", "Researches topics")
ctx.register_agent("writer", "Writes articles")

ctx.record_execution("researcher", {"in": "..."}, {"out": "..."})

# Writer sees what researcher did
writer_ctx = ctx.get_context_for_agent("writer")
GoalTracker โ€” Track progress
from splinter.coordination import GoalTracker, Goal

tracker = GoalTracker()

tracker.set_goal(Goal(
    goal_id="article",
    description="Write blog post",
    success_criteria=["Research", "Draft", "Review"],
))

tracker.mark_criterion_met("article", "Research")
tracker.update_progress("article", 0.33)

if tracker.is_achieved("article"):
    print("Done!")
ActionEligibility โ€” Who acts when
from splinter.coordination import ActionEligibility

elig = ActionEligibility()
elig.set_eligible("researcher")

elig.can_act("researcher")  # True
elig.can_act("writer")      # False

elig.transfer("researcher", "writer")
elig.can_act("writer")      # True
CompletionTracker โ€” "I'm done" signals
from splinter.coordination import CompletionTracker

tracker = CompletionTracker()
tracker.require_completion("researcher")
tracker.require_completion("writer")

tracker.declare_complete("researcher", output={...})
tracker.declare_complete("writer", output={...})

if tracker.all_complete():
    print("Workflow done!")
WaitTracker โ€” Why idle?
from splinter.coordination import WaitTracker, WaitReason

tracker = WaitTracker()
tracker.start_waiting("writer", WaitReason.WAITING_FOR_INPUT, "researcher")

reason, source = tracker.get_waiting_for("writer")
# WAITING_FOR_INPUT, "researcher"

tracker.stop_waiting("writer")

๐Ÿ”„ Full Example

from splinter.workflow import Workflow
from splinter.types import AgentConfig, ExecutionLimits, LLMProvider, LoopDetectionConfig

# Create workflow with all protections
workflow = Workflow(
    workflow_id="research-pipeline",
    limits=ExecutionLimits(
        max_budget=20.0,
        max_steps=200,
        max_time_seconds=600,
    ),
    loop_detection=LoopDetectionConfig(
        max_repeated_outputs=3,
        max_no_state_change=5,
    ),
    checkpoint_enabled=True,
)

# Add agents
workflow.add_agent(AgentConfig(
    agent_id="researcher",
    provider=LLMProvider.OPENAI,
    model="gpt-4o",
    system_prompt="Research. Output JSON.",
    tools=["web_search"],
    state_ownership=["research.*"],
))

workflow.add_agent(AgentConfig(
    agent_id="writer",
    provider=LLMProvider.ANTHROPIC,
    model="claude-sonnet-4-20250514",
    system_prompt="Write. Output JSON.",
    state_ownership=["content.*"],
))

# Define order
workflow.add_step("researcher")
workflow.add_step("writer", depends_on=["researcher"])

# Run
result = await workflow.run(initial_state={"topic": "AI trends"})

print(f"Success: {result.success}")
print(f"Cost: ${result.metrics['total_cost']:.4f}")

๐ŸŒ Providers

Provider Key Default Model
OpenAI openai_key="sk-..." gpt-4o-mini
Anthropic anthropic_key="sk-..." claude-sonnet-4-20250514
Gemini gemini_key="..." gemini-1.5-flash
Grok grok_key="xai-..." grok-3-mini-fast

Or use env vars: OPENAI_API_KEY, ANTHROPIC_API_KEY, GEMINI_API_KEY, XAI_API_KEY


๐Ÿงช Testing

pytest tests/ -v  # 102 tests, MockProvider, no keys needed

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

splinter_agent-0.1.0.tar.gz (108.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

splinter_agent-0.1.0-py3-none-any.whl (99.7 kB view details)

Uploaded Python 3

File details

Details for the file splinter_agent-0.1.0.tar.gz.

File metadata

  • Download URL: splinter_agent-0.1.0.tar.gz
  • Upload date:
  • Size: 108.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for splinter_agent-0.1.0.tar.gz
Algorithm Hash digest
SHA256 62d58e0eab6a3e6ee3cbaa9dfe06c656282648d55adb70323b42ac19d4dcf433
MD5 6f691ba523f96c512a833d933bed17a7
BLAKE2b-256 6acd627a0af7375e07e48ea74732d138b8135eed2bff93287fcd3a990ef77493

See more details on using hashes here.

File details

Details for the file splinter_agent-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: splinter_agent-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 99.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for splinter_agent-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e16433d82f888aa4903fc86d516d8812c6247071e3884ba9a27d8a64388872dc
MD5 6573d89010ca2f1b27bf926d8b0f6267
BLAKE2b-256 1a90afbebbd7c9f2c773a0767b4be23fd7791816539ac75c0f9842ce0d39f273

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page