Skip to main content
Once an agent makes a decision, it shouldn’t keep changing it. Decision enforcement locks decisions to prevent flip-flopping.

The Problem

Without enforcement, agents can:
  • Choose strategy A, then B, then A again
  • Waste tokens re-debating settled questions
  • Create inconsistent outputs

Basic Usage

from splinter.control import DecisionEnforcer, DecisionType

enforcer = DecisionEnforcer(auto_lock=True)

# Agent makes a decision
enforcer.record_decision(
    decision_id="strategy",
    agent_id="planner",
    decision_type=DecisionType.STRATEGY,
    value="parallel",
)

# Later, agent tries to change it
try:
    enforcer.record_decision(
        decision_id="strategy",
        agent_id="planner",
        decision_type=DecisionType.STRATEGY,
        value="sequential",  # Different value!
    )
except DecisionLockError:
    print("Can't change locked decision")

Decision Types

class DecisionType(Enum):
    STRATEGY = "strategy"      # How to approach the task
    TOOL_CHOICE = "tool"       # Which tool to use
    OUTPUT_FORMAT = "format"   # How to format output
    DELEGATION = "delegate"    # Who to hand off to
    CUSTOM = "custom"          # Your own types

Lock Modes

# Auto-lock: Lock immediately after first decision
enforcer = DecisionEnforcer(auto_lock=True)

# Manual lock: You control when to lock
enforcer = DecisionEnforcer(auto_lock=False)
enforcer.record_decision("strategy", "planner", DecisionType.STRATEGY, "parallel")
# ... agent can still change ...
enforcer.lock("strategy")  # Now locked

# Timed lock: Lock after N seconds
enforcer = DecisionEnforcer(lock_after_seconds=30)

Checking Decisions

# Is it locked?
if enforcer.is_locked("strategy"):
    print("Strategy is locked")

# What was decided?
decision = enforcer.get_decision("strategy")
print(f"Strategy: {decision.value}")  # "parallel"

# Who decided?
print(f"Decided by: {decision.agent_id}")  # "planner"

Overriding Decisions

Sometimes you need to override:
# Unlock (requires explicit override)
enforcer.unlock("strategy", reason="User requested change")

# Force new decision
enforcer.record_decision(
    decision_id="strategy",
    agent_id="admin",
    decision_type=DecisionType.STRATEGY,
    value="sequential",
    force=True,  # Override lock
)

Decision History

history = enforcer.get_history("strategy")
# [
#   {"value": "parallel", "agent": "planner", "time": "..."},
#   {"value": "sequential", "agent": "admin", "time": "...", "forced": True},
# ]

Best Practices

Don’t let agents waste tokens re-debating the approach.
output_format is better than decision_1.
Every forced override should have a reason.