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

# Build an agent loop

> observe → decide → act, efficiently and safely.

Every Glasswarp integration is the same shape. Glasswarp owns **observe** and
**act**; your model owns **decide**.

## The shape

```python theme={null}
import os
from glasswarp import GlasswarpClient

gw = GlasswarpClient(api_key=os.environ["GLASSWARP_API_KEY"])

rig = next(
    (r for r in gw.list_rigs() if r.online and r.api_access_enabled),
    None,
)
if rig is None:
    raise RuntimeError("No online rig with API access enabled")

session = gw.create_session(rig_id=rig.id, mode="desktop")
sid = session.session_id

try:
    for step in range(50):
        obs = gw.observe(sid, max_width=1280, mark=True)   # eyes
        action = decide(obs)                               # your brain
        if action is None:
            break
        act(gw, sid, action)                               # hands
finally:
    gw.end_session(sid)                                    # always clean up
```

`decide` and `act` are yours: `decide` calls your model with `obs.jpeg` and
`obs.targets`; `act` maps its output to `click_target`, `type_text`, etc.

## Make it cheap: skip idle frames

```python theme={null}
for step in range(200):
    if not gw.dirty_rects(sid):
        continue                       # nothing changed — no model call
    obs = gw.observe(sid, mark=True)
    ...
```

<Tip>
  Set `VP0` on in the example loops to skip idle frames by default. Empty
  `dirty_rects` means "don't spend a model call."
</Tip>

## Ground every action

Prefer `click_target` over raw pixels so the loop survives layout shifts:

```python theme={null}
obs = gw.observe(sid, mark=True)
target_id = decide(obs)                 # model returns a mark id
gw.click_target(sid, target_id, targets=obs.targets)
```

## Keep task logic out of the transport

<Note>
  Put prompts, CV, and planning in your own module. The Glasswarp client is a
  thin transport adapter — mixing task logic into it makes both harder to test.
</Note>

## Reference loops

The SDK ships runnable agent loops:

* `gemini_agent_loop.py` — CV grid → SoM targets → Gemini → `click_target`
* `claude_agent_loop.py` — observe → Claude → act (VP0 on by default)

See [Examples](/examples/paint).
