Skip to main content
Guides ••11 min read•

Decision Models as Agent Tools, a Builder's Rubric

Builders get a rubric for decision models as agent tools, from reasoning versus solving to typed contracts, infeasibility handling, and re-solve triggers.

Decision models as agent tools pairing an LLM's translation of intent with a solver's certified, machine-checkable answers.

Ask an LLM agent to outline a rollout plan and you get fluent, structured prose. Ask the same agent to place twelve engineers on eleven on-call shifts while honoring max-hours caps, visa work restrictions, and a hard rule against a third consecutive night, and the fluency keeps coming after the arithmetic has quietly left the room. Language models plan competently in natural language and allocate poorly under hard constraints, and reliability tends to fall as the allocation problem grows combinatorially.

Stay in the loop.

Get the latest posts and exclusive content delivered to your inbox.

Join 10 readers. No spam. Unsubscribe in one click, anytime.

That asymmetry is the whole argument for decision models as agent tools. The agent's job is translating messy human intent into a typed optimization model. The solver's job is owning the answer. Everything that decides whether the pairing survives production, status semantics, infeasibility diagnosis, re-solve triggers, lives in the tool contract, which is exactly the part most teams skip. This guide covers the rubric for when to hand off, the schemas that make the handoff safe, a debugging protocol for agent-authored infeasibility, and five failure modes to test your integration against.

Why Decision Models as Agent Tools Invert Control

Most agent tools retrieve, meaning search a corpus or query a table, or mutate, meaning write a file or deploy a service. In both shapes the model composes the final answer and the tool supplies raw material. A decision tool inverts that control flow: the model supplies raw material, an objective plus a set of constraints, and the tool returns the answer itself. Once the solver assigns shift 3 to engineer 7, the agent's prose is commentary on a decision that has already been made.

The inversion changes where failures come from. A bad retrieval integration produces vague answers a human catches in review. A bad decision-tool contract produces an agent that relaxes constraint sets which were satisfiable, or rebuilds its model from scratch on every state change because nobody defined a re-solve path. These production killers are contract bugs far more often than model bugs, which is good news, because you can test a contract, version it, and carry it across model upgrades.

So keep the division of labor strict. The agent elicits requirements, names tradeoffs, and decides what "best" means. The solver runs bounded, exhaustive search over whatever it is handed, a linear program, a mixed-integer program, or a constraint-programming model. That whole family shares the properties that matter here: answers you can check mechanically, and optimality claims that arrive with proof attached.

The Rubric for Reasoning in Language Versus Handing Off to a Solver

Decision flowchart for when an LLM agent should call a solver instead of reasoning in natural language.

When should an LLM agent call a solver instead of reasoning in context? Four signals, and the more that light up at once, the stronger the case:

SignalQuestion to askWhat it implies
Hard constraintsWould any violation be unacceptable, legally, contractually, or for safety?Language reasoning gambles; a solver never returns an assignment that breaks a stated rule
Combinatorial sizeDoes the space explode? Twelve engineers across eleven shifts is roughly 740 billion raw combinationsThe model cannot enumerate, so it samples and hopes
OptimalityIs any valid plan enough, or do you want the cheapest, fastest, or fairest?A solver returns a bound that proves how close to optimal you landed
Repeat decisionsWill you re-make this call as resources and requests change?A standing model amortizes framing cost across every re-solve

Shift scheduling lights all four. Drafting the tone of an incident update lights none, since it has no constraint structure, a tiny space, and a one-off shape, so keep it in language. The gray zone is a choice like picking between five vendors with qualitative tradeoffs: if the criteria can be quantified into a scoring model, hand off, and if they stay soft and negotiable, forcing them into hard constraints manufactures false infeasibility while the agent reasoning aloud explains itself better anyway. For purely continuous allocations such as splitting a budget, a plain linear program is often enough, and the OR-Tools LP example is a fine skeleton to start from.

The Tool Contract: Typed Models In, Certificates Out

Agent tool contract design for decision tools starts at the schema, because the schema is where translation bugs either die or multiply.

Input, a typed model of intent

The input schema carries:

  • objective, typed as sense plus a named term, such as minimize overtime hours
  • decision variables with explicit domains
  • constraints, each with a stable ID and a provenance string naming the user requirement it encodes
  • units and bounds on every numeric field, hours versus minutes, epoch versus index, inclusive versus exclusive windows
  • time_limit_ms, on every call, no exceptions

Most translation bugs, unit mismatches, index shifts, and ambiguous time windows among them, are prevented at authoring time by making units and bounds part of the type instead of a comment. Before the solve fires, also run a round-trip check in plain code: every stated user requirement maps to a constraint ID, and every constraint ID maps back to a requirement. The constraint the model silently forgot to encode is the most dangerous bug in the stack, because nothing errors.

Output, a status and its evidence

Never return a natural language summary as the only result. Narration is the agent's job; the tool returns machine-checkable facts:

{
  "status": "OPTIMAL",
  "objective_value": 4120.0,
  "objective_bound": 4120.0,
  "solution": {"s_1": "eng_7", "s_2": "eng_3"},
  "evidence": {"solver": "cp-sat", "presolve_removed_vars": 34, "log_tail": "..."},
  "elapsed_ms": 812
}

The status enum has five members: OPTIMAL, FEASIBLE, INFEASIBLE, NO_ANSWER_IN_BUDGET, and UNBOUNDED. The objective_value and objective_bound pair is what turns an answer into a certificate: for a minimization, a bound within one percent of the value proves you are within one percent of optimal, and downstream code can verify the assignment against the constraints without trusting anyone's prose.

One schema, every consumer

Define the input and output schemas once in code and generate the tool definition from them; Pydantic JSON Schema export does this for Python, so the wire contract and your validation logic cannot drift apart. The same pair of schemas then serves every consumer, whether you wire OpenAI function calling or Claude tool use into the loop directly. Exposing an optimization solver as an MCP tool is mostly a matter of wrapping this contract in a server, since the protocol already speaks JSON Schema. Structured outputs for tool schemas are the mechanism LLM tool calling already uses; your job is making the schema worth trusting.

Infeasibility Usually Means the Agent Authored a Bad Model

Debugging session for infeasible constraints generated by an LLM, isolating the minimal conflicting rules before any retry.

When the solve returns INFEASIBLE, do not retry. The solver proved something real: no assignment satisfies the constraints as written. The open question is whether the constraints as written are the constraints the user meant. Debugging infeasible constraints generated by an LLM is translation debugging, and blind retries just re-roll the translation.

Run this protocol instead:

  1. Elastic relaxation first. Re-solve with slack variables and penalties on each constraint; the constraints that absorb slack form your conflict set. Cheap, and every solver supports it.
  2. Compute an irreducible infeasible subsystem (IIS). This is the minimal subset of constraints that stays infeasible when everything else is dropped. Gurobi infeasibility analysis documents the canonical implementation, and CP-SAT can report sufficient assumptions for infeasibility, which serves the same diagnostic job.
  3. Return the IIS with provenance. The agent's next move is one targeted question, not improvisation: r_12 says engineer 4 covers shift 9, r_20 says engineer 4 is on leave that week, which one gives?
  4. Loosen one constraint, with confirmation. The agent proposes relaxing one specific, provenance-labeled rule and the user confirms. It never drops constraints silently to force feasibility.

The contract implication is direct: expose a diagnose flag, or always attach diagnosis fields to an infeasible status. A bare INFEASIBLE invites the thrash loop.

Latency, Time Budgets, and Where the Solver Sits in the Loop

Many planning problems of this shape are NP-hard, so worst-case solve time is unbounded, and presolve alone can dominate on badly scaled models. Two consequences follow for any agent loop.

First, every solver call inside the loop carries an explicit time limit, and the contract documents the fallback for an exhausted budget before the agent ever hits it: return the best incumbent with its gap, simplify the model, or fail the turn cleanly. Improvised fallbacks are how satisfiable problems get their constraints relaxed.

Second, a solver timeout must be a distinct status from proved infeasibility. The CP-SAT solver guide distinguishes a proved INFEASIBLE result from an UNKNOWN outcome when a time limit stops the search, and the HiGHS solver guide exposes the same distinction for open-source MILP work. If your contract collapses both into one failed path, the agent will eventually treat a slow but solvable model as impossible and start deleting constraints that were fine.

Placement patterns that hold up in production:

  • Inline sync for models that solve well under a second after presolve; the call looks like any other tool call.
  • Async job for long solves: submit, hold a handle, resume when the result lands, keeping turns responsive.
  • Cache by model hash so parameter-only repeats across turns never pay for the same solve twice.

Re-Solve Triggers, or When Solving Beats Re-Planning

State changes constantly in production: an engineer calls in sick, a request lands, a deadline moves. The re-solve versus re-plan question in agent loops has a default answer, which is to patch the standing model and re-solve.

TriggerExampleCorrect action
Parameter shifta resource becomes unavailable, demand changespatch parameters, warm-start from the last solution, re-solve
Constraint editthe user adds a ruleupdate the constraint set, re-solve
Objective changeminimize cost becomes maximize fairnessre-frame, the agent re-authors the model

Re-solving usually wins on three counts. The standing model already encodes the objective and every constraint, so the agent edits numbers instead of re-deriving the framing in tokens. Warm-starting from the previous solution hands the solver a strong incumbent, which typically shortens the re-solve. And consecutive answers stay comparable because they come from one fixed model, while LLM re-plans can drift, silently dropping between turns a constraint nobody removed. The exception is the third row: when the definition of "best" changes, patching parameters is wrong, because the objective itself is part of the framing, and framing is the agent's department.

5 Failure Modes That Sink Solver-Backed Agents in Production

Audit your integration against all five:

1) The tool narrates instead of certifying. Symptom: responses read "here is a good schedule" with no status, bound, or machine-readable assignment. Root cause: the tool was built to please the model rather than the pipeline. Fix: certificate out, status plus value plus bound plus solution, and let the agent narrate on top.

2) Timeout is reported as infeasible. Symptom: answer quality degrades exactly when load spikes or the model grows. Root cause: one boolean failure path. Fix: five statuses and a written policy for the budget-exhausted one.

3) Bare INFEASIBLE with no diagnosis. Symptom: the agent blind-retries with increasingly inventive constraint sets and thrashes. Root cause: the contract optimizes for the happy path. Fix: elastic slack and an IIS in every infeasible response, provenance attached.

4) Unit and index drift. Symptom: plans that are technically feasible but practically absurd, or valid inputs rejected as infeasible. Root cause: hours versus minutes, Monday as 0 versus 1, ambiguous windows. Fix: units and bounds in the schema plus round-trip validation before the solve.

5) Re-planning on every state change. Symptom: latency and token cost climb while consecutive answers disagree about constraints nobody touched. Root cause: no standing model and no re-solve path. Fix: parameter patch plus warm-started re-solve, with re-framing reserved for objective changes.

A Reference Contract and When You Do Not Need a Solver

A compact sketch of the pattern, a shift-scheduling solve exposed as an MCP tool:

{
  "name": "solve_shift_schedule",
  "description": "Assigns staff to shifts under hard constraints. Returns a status, objective value and bound, and the assignment.",
  "input_schema": {
    "staff": [{"id": "eng_1", "role": "oncall", "max_hours_per_week": 40, "unavailable": ["2026-11-05"]}],
    "shifts": [{"id": "s_1", "start_utc": "2026-11-02T08:00Z", "hours": 8, "required_role": "oncall"}],
    "rules": [{"id": "r_1", "provenance": "user: no third consecutive night", "type": "max_consecutive_nights", "value": 2}],
    "objective": {"sense": "minimize", "term": "total_overtime_hours"},
    "time_limit_ms": 5000
  }
}

Every field earns its place: provenance on rules, explicit units on times, a time limit on every call. Decision models as agent tools tend to fail at the seam between intent and model, so the seam is where the engineering budget belongs.

Know when to skip the solver, too. If the choice space is small enough to compare in context, plain reasoning is fine. If the constraints are soft, negotiable, or genuinely qualitative, hard-constraint modeling manufactures false infeasibility. If the decision is a one-off a human will review anyway, the schema costs more than it returns. Everything else, routing, packing, budget splits, rollout ordering under dependency constraints, is framing plus a solve, and the certificate does the talking.

Stay in the loop.

Get the latest posts and exclusive content delivered to your inbox.

Join 10 readers. No spam. Unsubscribe in one click, anytime.

About the author

David Moreno

Applied AI Strategist

David helps teams put AI to work in real businesses. He writes teardowns of how companies actually deploy models: the architectures, the trade-offs, and the results that survive contact with the real world.

Related Posts