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. 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
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.