> ## Documentation Index
> Fetch the complete documentation index at: https://splinter.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Decision Enforcement

> Lock decisions to prevent flip-flopping

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

```python theme={null}
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

```python theme={null}
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

```python theme={null}
# 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

```python theme={null}
# 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:

```python theme={null}
# 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

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

## Best Practices

<AccordionGroup>
  <Accordion title="Lock strategic decisions early">
    Don't let agents waste tokens re-debating the approach.
  </Accordion>

  <Accordion title="Use meaningful decision IDs">
    `output_format` is better than `decision_1`.
  </Accordion>

  <Accordion title="Log overrides">
    Every forced override should have a reason.
  </Accordion>
</AccordionGroup>
