# Build a small terminal interface for your agent

Expose progress, reference reads, and resumable steps with a portable Python terminal interface.

## Put a terminal interface around the same worker

A terminal interface should reveal what the application is doing: which step ran, which reference was read, and whether the task finished. Reuse `mandapi_worker.py` from the [headless guide](/en/cookbook/building-agents/headless-agent/). This small, portable interface uses standard Python input and output rather than a separate agent SDK.

Save the code as `agent_tui.py` beside that module. `/next` admits one step, `/status` shows saved progress, and `/quit` leaves the last checkpoint available. Only the fixed reference reader is enabled. The interface does not grant the model shell access or create a hosted MandAPI agent.

## Add the interface

```python
import argparse
import os
from pathlib import Path
from mandapi_worker import load_state, step, chat, demo, MAX_STEPS


def safe(text):
    return "".join(c for c in str(text) if c.isprintable() or c == "\n")


def show_event(event):
    if event["event"] == "read":
        print("  reference:", safe(event["name"]))
    elif event["event"] == "done":
        print("  answer:", safe(event["answer"]))
    else:
        print("  status:", safe(event["event"]))


def run_ui(state, checkpoint, ask, read=input):
    while state["status"] == "ready":
        print("\n+--- MandAPI demo assistant ---+")
        print("attempts:", state["attempts"], "/", MAX_STEPS)
        print("/next = one step | /status | /quit")
        command = read("> ").strip()
        if command == "/quit":
            return state
        if command == "/status":
            print("status:", safe(state["status"]))
        elif command == "/next":
            print("working...", flush=True)
            step(state, checkpoint, ask, show_event)
        else:
            print("Unknown command")
    print("status:", safe(state["status"]))
    if state["result"]:
        print(safe(state["result"]))
    return state


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("job")
    parser.add_argument("--checkpoint", type=Path, default=Path("tui-run.json"))
    parser.add_argument("--demo", action="store_true")
    args = parser.parse_args()
    model = "offline-demo" if args.demo else os.environ["MANDAPI_MODEL_ID"]
    state = load_state(args.checkpoint, args.job, model)
    try:
        run_ui(state, args.checkpoint, demo if args.demo else chat)
    except (EOFError, KeyboardInterrupt):
        print("\nStopped; the last saved checkpoint remains available.")
    except (OSError, ValueError, KeyError, TypeError, IndexError) as error:
        print("Stopped:", type(error).__name__)
        raise SystemExit(1)
```

## Try the interaction

Run `python agent_tui.py "How long does demo shipping take?" --demo --checkpoint tui-demo.json`. Enter `/status`, then `/next` twice. Expect a reference name and a final answer. Repeat the command with the same task and checkpoint to see the completed result without another model call.

For live chat, set `MANDAPI_API_KEY` and a suitable `MANDAPI_MODEL_ID`, omit `--demo`, and use a new checkpoint. The reused worker sends ordinary requests to `https://api.mandapi.com/v1/chat/completions`; every admitted live step can consume credits. It displays a waiting message and then the completed step, rather than token streaming.

## Verify the controls

Try an unknown command and confirm it makes no request. Quit before `/next` and confirm the model was never called. Test an invalid model action and verify the worker rejects it. Display text removes terminal control characters before printing; avoid rendering raw model output as escape sequences.

Stopping the UI does not cancel an already accepted remote request. A failed or interrupted attempt remains counted. For unattended execution, keep the same worker and follow [resumable tasks](/en/cookbook/building-agents/long-horizon/).

## References

- [https://openrouter.ai/docs/cookbook/building-agents/create-agent-harness-tui](https://openrouter.ai/docs/cookbook/building-agents/create-agent-harness-tui)
