# Agents

Source: https://docs.temprl.org/guide/agents

> Use Simo to choose an agent's next tool call with a calibrated probability and generated arguments, and stop to hand over when it is unsure.

An agent step is a decision: *which action next, with which arguments?* Simo answers it as a `Choice` over your actions, generates the arguments for the chosen one in the same request, and gives you a calibrated probability. Below your threshold, the agent stops and hands over instead of guessing.

## Decide one step

```python
from simoai import Client, Agent, Extract, Fill, Noul

c = Client()
agent = Agent(c,
    actions={"lookup_order": "look up an order by its number",
             "issue_refund": "refund an order",
             "ask_customer": "ask the customer a question",
             "close_ticket": "close the ticket"},
    args={"lookup_order": {"order_id": Extract("the order number to use, exactly as written", max_tokens=8)},
          "issue_refund": {"order_id": Extract("the order number"),
                           "amount": Fill("the refund amount", kind="number")},
          "ask_customer": {"question": Fill("the question to ask, one short sentence", max_tokens=32)}},
    question="Following the policy and what has happened so far, what is the agent's next action?",
    act_at=0.8,                                  # below this, stop and hand over
    extra={"angry": Noul("The customer is angry")})

d = agent.decide({"policy": POLICY, "ticket": ticket_text, "history": "(nothing yet)"})
d.action, d.args, d.p     # "lookup_order", {"order_id": "A-1042"}, 0.97
d.confident               # True: p >= act_at
d.probabilities           # over every action
d.call                    # "lookup_order(order_id='A-1042')"
d.extra                   # {"angry": False}
```

`extra` adds side questions answered in the same request, such as a mood flag for escalation. The agent's own question id is `action`, so don't use it in `extra`.

## Run a loop

Give `agent.run` an environment with `state()`, `act(action, args)` and `done`:

```python
from simoai import History

class Env:
    def __init__(self):
        self.history = History()
        self.done = False

    def state(self):                    # may also return (state, media) for screenshots
        return {"policy": POLICY, "ticket": ticket_text, "history": str(self.history)}

    def act(self, action, args):
        result = TOOLS[action](**args)
        self.history.add(f"{action}({args})", result)
        self.done = action == "close_ticket"
        return result

run = agent.run(Env(), max_steps=20)
run.finished, run.reason, run.calls     # True, "done", ["lookup_order(...)", "issue_refund(...)", ...]
```

`agent.run` also takes `on_step` (called after each step; return `False` to stop) and `on_uncertain` (called with a decision below `act_at`; return `True` to act on it anyway). `run.steps` holds each decision and what `act` returned.

`run.reason` is one of:

| Reason | Meaning |
|---|---|
| `done` | The environment reported `done` |
| `uncertain` | A step fell below `act_at`: hand over to a person |
| `max_steps` | Hit `max_steps` |
| `stopped` | `on_step` returned `False` |

## Without the Agent class

Under the hood a step is a single `Choice` with `args`. Over HTTP:

```json
{
  "model": "simo-1-pro",
  "state": {"policy": "...", "ticket": "...", "history": "(nothing yet)"},
  "questions": {
    "action": {
      "type": "choice",
      "instructions": "Following the policy and what has happened so far, what is the agent's next action?",
      "criteria": {"lookup_order": "look up an order by its number", "issue_refund": "refund an order",
                   "ask_customer": "ask the customer a question", "close_ticket": "close the ticket"},
      "args": {"lookup_order": {"order_id": {"type": "extract", "instructions": "the order number to use, exactly as written",
                                             "kind": "text", "many": false, "max_tokens": 8}}}
    }
  }
}
```

Read `answers.action.choice`, its probability in `answers.action.probabilities`, and the arguments in `answers.action.args`. See the [tool-calling agent example](https://docs.temprl.org/examples/tool-calling-agent) and the [browser agent example](https://docs.temprl.org/examples/browser-agent).
