Contents · 16 sections↓
- 01How do you monitor AI agents in a terminal dashboard?
- 02What does an AI agent monitoring dashboard show?
- 03When to use the terminal dashboard (and when not to)
- 04What you need
- 05Step 1: Start the runtime with the dashboard
- 06Step 2: Check processes and triggers
- 07Step 3: Inspect context state
- 08Step 4: Read logs and events
- 09Step 5: Control processes with commands
- 10Step 6: Embed the dashboard in your own program
- 11Running it in production
- 12Common problems and fixes
- 13How is it different from promptise run --tui?
- 14Limitations
- 15Frequently asked questions
- 16Next steps
An AI agent monitoring dashboard shows, in one screen, what your long-running agents are doing right now: which ones run, which triggers fired, what state they keep and whether their last runs failed. This guide is for developers who run scheduled or event-driven agents and want that view in a terminal, without setting up a metrics stack. You will start the Promptise Foundry runtime with its built-in terminal dashboard, read every tab, control processes with its commands, and embed it in your own program.
How do you monitor AI agents in a terminal dashboard?
Start the agents with promptise runtime start agents/ --dashboard. The runtime loads every .agent manifest in the folder, starts the processes and replaces its status table with a full-screen dashboard. Seven tabs show the overview, each process, the triggers with their fire counts, each process's context state, captured logs and journal entries, trigger events with run results, and a command line. Press 1 to 7 to switch tabs, : to type a command such as suspend pipeline-watcher or inject report-writer {"topic": "weekly"}, and Ctrl+C to stop every process and leave.
pip install "promptise>=1.5.0"
promptise runtime start agents/ --dashboardKey takeaways:
One command, no extra services. The dashboard reads the runtime in the same process; there is nothing to deploy or configure.
Seven tabs cover state, triggers, context, logs and events. Run results and trigger events arrive through lifecycle hooks the dashboard registers.
Commands work in 1.5.0. start, stop, restart, suspend, resume and inject now run on the runtime's event loop; in 1.4 they were accepted but never ran.
It is a local tool. It needs a foreground terminal, can't be combined with --detach, and is meant for development, demos and a quick look on a server over SSH.
It differs from `promptise run --tui`, which traces one run of a Python program call by call. The runtime dashboard watches long-running processes.
[02]
What does an AI agent monitoring dashboard show?
A long-running agent fails differently from a web request. It doesn't crash with a stack trace in front of you; it stops firing, falls behind, loops quietly, or keeps the wrong state. A useful dashboard for such agents answers a handful of questions at a glance:
Is each agent running? Its lifecycle state, uptime and consecutive failures.
Is it being woken up? Each trigger, how often it fired and when it last fired.
Did its runs work? Recent runs, their outcome and duration, and the error if one failed.
What does it believe? The state it keeps between runs.
What happened in detail? Logs and the journal of tool calls and checkpoints.
Is work piling up? The queue of events waiting for a run.
How the Promptise runtime dashboard gets its data
runtime process (one Python process, one event loop)
┌───────────────────────────────────────────────────────────────────────┐
│ AgentRuntime ── AgentProcess "pipeline-watcher" AgentProcess "..." │
│ │ │ task_created / task_completed hooks │
│ │ ▼ │
│ │ RuntimeDataCollector (thread, every 0.5 s) │
│ ├────▶ status(), config, context state ──▶ RuntimeDashboardState
│ │ journal read every 4th snapshot ──▶ processes, triggers,
│ │ contexts, events,
│ │ Python log records ──────────────────▶ runs, journal, logs
│ │ │
│ │ RuntimeDashboard (rich, redraws 4 times a second) ◀┘
│ │ key reader (thread) ── commands ──▶ run on the event loop
│ │
│ control API on 127.0.0.1 (as without --dashboard)
└───────────────────────────────────────────────────────────────────────┘Three parts work together. RuntimeDataCollector is a background thread that snapshots every process twice a second, registers a task_created and a task_completed lifecycle hook on each process for trigger events and run results, and reads the newest journal entries every fourth snapshot. RuntimeDashboardState holds the snapshots and ring buffers (200 runs, 200 events, 500 journal entries, 100 commands). RuntimeDashboard draws the state with rich in the terminal's alternate screen, reads keys in another thread, and captures Python log records for the Logs tab. Context values are shown with secret values redacted, as in the journal.
[03]
When to use the terminal dashboard (and when not to)
You want to | Use |
|---|---|
Watch agents while you develop or demo them |
|
Check a runtime from a script or another terminal | promptise runtime status and logs --follow (AI agent CLI) |
See every LLM call, tool call, token and cost of a Python program | promptise run --tui |
Monitor production agents over time, with alerts | The control API, health checks and an observability backend |
The dashboard has no history beyond its ring buffers, no alerts and no remote view. It shows what happens while it runs. For a production runtime, run it in the foreground under a supervisor without the dashboard, and look at it from outside with the CLI and the API. AI agent health monitoring covers what to alert on.
[04]
What you need
Python 3.10 or later and Promptise Foundry 1.5.0 or later.
An OpenAI API key in OPENAI_API_KEY; the agents use openai:gpt-5-mini, a fraction of a cent per run.
A real terminal (not an IDE output pane) at least 100 columns wide. The captures in this guide are 104 columns wide; the Processes tab needs about 170 to show full names.
Two manifests in agents/: the pipeline watcher from the AI agent CLI guide, with a cron trigger every 30 seconds, and a report writer that runs when you inject an event:
version: "1.0"
name: report-writer
model: openai:gpt-5-mini
instructions: |
You write one-line status reports for the operations channel.
Use the topic in the trigger payload. Then increase reports_written by one
with update_state.
triggers:
- type: webhook
webhook_path: /report
webhook_port: 9092
world:
reports_written: 0
channel: "#ops"
context:
writable_keys: [reports_written]
state_tool: true
journal:
level: fullThe report writer has a webhook trigger, so it does nothing until something calls it. Its state has a key it may write and one it may not, which the Context tab shows.
[05]
Step 1: Start the runtime with the dashboard
Run start on the directory with --dashboard:
promptise runtime start agents/ --dashboardEverything start normally does still happens: the manifests load, the control API starts on loopback and the runtime is recorded in its state file. Then the dashboard takes over the terminal. This is the Overview tab 44 seconds later, after the first scheduled run (empty rows removed):
╭──────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ █████████████████████████████ │
│ █████ ██████ P R O M P T I S E │
│ █████ █████ Agent Runtime │
│ █████ █████ │
│ █████ ██████ Runtime agents │
│ ██████████████████████████ Uptime 44s │
│ █████ │
│ █████ ░▒▓██████▓▒░ Processes 2 (2 running) │
│ █████ ░▒████▓░ Triggers 2 configured │
│ ████░ ░▒██▓ Events 1 │
│ ░███▓░ ░▒██▓░ │
│ ░███▓░ ░▒▓██▓░ promptise.com · promptise.com/docs │
│ ░▒▓▓▓▓▒░ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯
1 Overview 2 Processes 3 Triggers 4 Context 5 Logs 6 Events 7 Commands
╭────────────────────────────────────────────── Overview ──────────────────────────────────────────────╮
│╭───────────────────────────────────────────── Metrics ──────────────────────────────────────────────╮│
││ 2 2 1 0.02/s ││
││ Processes Running Invocations Throughput ││
││ 2 0 0 44s ││
││ Triggers Failed Errors Uptime ││
│╰────────────────────────────────────────────────────────────────────────────────────────────────────╯│
│╭──────────────────────────────────────────── Processes ─────────────────────────────────────────────╮│
││ Process ┃ State ┃ Invocations ┃ Queue ┃ Uptime ││
││ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━ ││
││ pipeline-watcher │ RUNNING │ 1 │ 0 │ 44s ││
││ report-writer │ RUNNING │ 0 │ 0 │ 44s ││
│╰────────────────────────────────────────────────────────────────────────────────────────────────────╯│
│╭───────────────────────────────────────── Recent Activity ──────────────────────────────────────────╮│
││ Time ┃ Process ┃ Trigger ┃ Status ┃ Duration ││
││ ━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━ ││
││ 22:44:40 │ pipeline-watcher │ cron │ OK │ 10.7s ││
│╰────────────────────────────────────────────────────────────────────────────────────────────────────╯│
╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯
← → Navigate 1-7 Jump Tab Next : Command Ctrl+C QuitThe header names the runtime (the directory name), its uptime and the counts. The Metrics panel shows processes, running processes, runs ("Invocations"), runs per second, triggers, failed processes, failed runs ("Errors") and uptime. The Processes panel lists each process with its state, runs, queue and uptime. Recent Activity shows the last five runs: the pipeline watcher's cron run took 10.7 seconds and succeeded. States are colored: running is green, starting, suspended and stopping are yellow, stopped is red, failed is bold red.
Because the runtime is recorded as usual, other terminals still work while the dashboard runs:
$ promptise runtime status
Runtime agents pid 72734 API http://127.0.0.1:50048 started 2026-10-20T20:44:17+00:00
Agent Processes
┏━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━┓
┃ Name ┃ State ┃ ID ┃ Invocations ┃ Queue ┃ Uptime ┃
┡━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━┩
│ pipeline-watcher │ RUNNING │ ecd2bb4a │ 3 │ 0 │ 0h 1m 43s │
│ report-writer │ RUNNING │ 5c1ee5f0 │ 1 │ 0 │ 0h 1m 43s │
└──────────────────┴─────────┴──────────┴─────────────┴───────┴───────────┘[06]
Step 2: Check processes and triggers
Press 2 for the Processes tab. It adds the process ID, model, consecutive failures, configured triggers, concurrency and heartbeat interval. The table has eleven columns, so it needs a wide terminal; this is the same tab at 170 columns:
…
1 Overview 2 Processes 3 Triggers 4 Context 5 Logs 6 Events 7 Commands
╭────────────────────────────────────────────────────────────────────────────── Processes ───────────────────────────────────────────────────────────────────────────────╮
│ Name ┃ State ┃ PID ┃ Model ┃ Invocations ┃ Failures ┃ Triggers ┃ Queue ┃ Conc. ┃ Heartbeat ┃ Uptime │
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━ │
│ pipeline-watcher │ RUNNING │ ecd2bb4a │ openai:gpt-5-mini │ 1 │ 0 │ 1 │ 0 │ 1 │ 10s │ 46s │
│ report-writer │ RUNNING │ 5c1ee5f0 │ openai:gpt-5-mini │ 0 │ 0 │ 1 │ 0 │ 1 │ 10s │ 46s │
│ 2 processes Use ':help' for process commands │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
← → Navigate 1-7 Jump Tab Next : Command Ctrl+C QuitAt 104 columns the Name and Model columns collapse completely, and at 140 they are cut to a few characters. The Overview tab shows the names at any width.
Press 3 for the Triggers tab: every configured trigger with its process, type, a short configuration and how often it fired:
…
1 Overview 2 Processes 3 Triggers 4 Context 5 Logs 6 Events 7 Commands
╭────────────────────────────────────────────── Triggers ──────────────────────────────────────────────╮
│ Process ┃ Type ┃ Configuration ┃ Fires ┃ Last Fired │
│ ━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━━ │
│ pipeline-watcher │ ⏰ cron │ cron=* * * * * */30 │ 2 │ 22:45:00 │
│ report-writer │ 🌐 webhook │ port=9092 path=/report │ 0 │ - │
│ 2 triggers 1 cron 1 webhook │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯
← → Navigate 1-7 Jump Tab Next : Command Ctrl+C QuitFire counts come from the task_created hook, so they count events as they are queued, including ones whose run later fails. A trigger that never fires when it should is the first thing to look for here: a wrong cron expression or time zone, or a webhook nobody calls. Triggers an open-mode agent adds at runtime aren't listed; the tab shows the configured ones.
[07]
Step 3: Inspect context state
Press 4 for the Context tab. It shows each process's context state, whether the agent may write each key and how many writes it has had. This capture was taken after the commands in step 5:
…
1 Overview 2 Processes 3 Triggers 4 Context 5 Logs 6 Events 7 Commands
╭────────────────────────────────────────────── Context ───────────────────────────────────────────────╮
│╭───────────────────────────────────────── pipeline-watcher ─────────────────────────────────────────╮│
││ Key ┃ Value ┃ Writable ┃ Writes ││
││ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━ ││
││ open_alerts │ ['billing-sync'] │ yes │ 2 ││
││ no extra config ││
│╰────────────────────────────────────────────────────────────────────────────────────────────────────╯│
│╭────────────────────────────────────────── report-writer ───────────────────────────────────────────╮│
││ Key ┃ Value ┃ Writable ┃ Writes ││
││ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━ ││
││ channel │ #ops │ no │ 1 ││
││ reports_written │ 1 │ yes │ 2 ││
││ no extra config ││
│╰────────────────────────────────────────────────────────────────────────────────────────────────────╯│
╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯
← → Navigate 1-7 Jump Tab Next : Command Ctrl+C QuitThe pipeline watcher saved ['billing-sync'] with its update_state tool. The report writer raised reports_written to 1 after the injected run. The write count includes the initial value, which is why channel, a key no run changed, shows 1. Values longer than 50 characters are cut, and secret values are [REDACTED]. The line under each table lists environment variables, file mounts and memory when the process has them. AI agent state between runs explains context state.
[08]
Step 4: Read logs and events
Press 6 for the Events tab. The upper table lists trigger events as they enter the queue; the lower one lists finished runs with status, duration and error:
…
1 Overview 2 Processes 3 Triggers 4 Context 5 Logs 6 Events 7 Commands
╭─────────────────────────────────────────────── Events ───────────────────────────────────────────────╮
│╭────────────────────────────────────────── Trigger Events ──────────────────────────────────────────╮│
││ Time ┃ Process ┃ Trigger ┃ Event ID ┃ Payload ││
││ ━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ││
││ 22:45:00 │ pipeline-watcher │ cron │ 9c58d09c │ - ││
││ 22:44:30 │ pipeline-watcher │ cron │ b2db803b │ - ││
│╰────────────────────────────────────────────────────────────────────────────────────────────────────╯│
│╭──────────────────────────────────────── Invocation Results ────────────────────────────────────────╮│
││ Time ┃ Process ┃ Trigger ┃ Status ┃ Duration ┃ Error ││
││ ━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ││
││ 22:45:10 │ pipeline-watcher │ cron │ OK │ 10.8s │ - ││
││ 22:44:40 │ pipeline-watcher │ cron │ OK │ 10.7s │ - ││
│╰────────────────────────────────────────────────────────────────────────────────────────────────────╯│
│ 2 events 2 invocations 2 ok 0 errors │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯
← → Navigate 1-7 Jump Tab Next : Command Ctrl+C QuitEach cron tick at :00 and :30 produced one event, and each run finished about ten seconds later. A run that is retried is counted once, when it finally ends. The Payload column shows -: the collector doesn't summarize payloads.
Press 5 for the Logs tab. Its upper panel shows captured Python log records, newest first; the lower panel shows the newest journal entries of every process. While the dashboard runs, the root logger is set to DEBUG and console handlers are muted, so the upper panel fills with debug records from the HTTP client as well as the runtime's own:
╭──────────────────────────────────────────────── Logs ────────────────────────────────────────────────╮
│╭─────────────────────────────────────────── Runtime Logs ───────────────────────────────────────────╮│
││ 22:45:10.756 DEBUG promptise.runtime.process AgentProcess pipeline-watcher: invocation #2 ││
││ complete ││
││ 22:45:10.755 DEBUG openai._base_client request_id: ││
││ req_aaf2e6c2e25541b38f8ad0ecbfe29e33 ││
││ 22:45:10.755 DEBUG openai._base_client HTTP Response: POST 200 ││
││ 22:45:10.755 DEBUG httpcore.http11 response_closed.complete ││
…The upper panel keeps the last 60 records, which fill a normal terminal, so the Journal Entries panel below it is only visible in a very tall window. At 130 rows it appears:
│╭───────────────────────────────────────── Journal Entries ──────────────────────────────────────────╮│
││ 2026-10-20T20:45:10 checkpoint pipeline-watcher {"state": {"context_state": ││
││ {"open_alerts": ["billing-sync"]}, "lifecycle_sta... ││
││ 2026-10-20T20:45:10 invocation_result pipeline-watcher {"invocation": 2, "event_id": ││
││ "9c58d09c-67b4-4f9f-b009-7724cd3accea", "trigge... ││
││ 2026-10-20T20:45:03 tool_result pipeline-watcher {"tool": "pipeline_status", "result": ││
││ "{\"orders-etl\": {\"status\": \"health... ││
││ 2026-10-20T20:45:03 tool_call pipeline-watcher {"tool": "pipeline_status", "args": {}} ││
╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯For the journal of one process in a normal terminal, run promptise runtime logs <process> --follow in a second window.
[09]
Step 5: Control processes with commands
Press : (or /) to type a command; the Commands tab opens. Enter runs it, Esc cancels, Backspace deletes. The commands:
Command | What it does |
|---|---|
help, list | List the commands, or the process names |
| Count running processes, or show one process's state, runs and queue |
start <name>, stop <name> | Start or stop a process |
restart <name> | Restart a process (AgentRuntime.restart_process()) |
suspend <name>, resume <name> | Pause a process (triggers keep queueing) and continue it |
| Queue a manual trigger event with this payload; text that isn't JSON becomes {"raw": "..."} |
This session injected an event into the report writer, suspended and resumed the pipeline watcher, and tried two commands that fail:
:inject report-writer {"topic": "weekly numbers"}
:suspend pipeline-watcher
:status pipeline-watcher
:resume pipeline-watcher
:start report-writer
:stop nobody…
1 Overview 2 Processes 3 Triggers 4 Context 5 Logs 6 Events 7 Commands
╭────────────────────────────────────────────── Commands ──────────────────────────────────────────────╮
│╭─────────────────────────────────────────────── Help ───────────────────────────────────────────────╮│
││ Available Commands: ││
││ help Show this help message ││
││ list List all registered processes ││
││ status [name] Show process status (all or specific) ││
││ start <name> Start a stopped process ││
││ stop <name> Stop a running process ││
││ restart <name> Restart a process ││
││ suspend <name> Suspend a process (triggers still queue) ││
││ resume <name> Resume a suspended process ││
││ inject <name> [json] Inject a manual trigger event ││
││ Press ':' or '/' to enter command mode, then type your command. ││
│╰────────────────────────────────────────────────────────────────────────────────────────────────────╯│
│╭────────────────────────────────────────── Command Input ───────────────────────────────────────────╮│
││ Press ':' to enter a command... ││
│╰────────────────────────────────────────────────────────────────────────────────────────────────────╯│
│╭───────────────────────────────────────── Command History ──────────────────────────────────────────╮│
││ Time ┃ Command ┃ Result ┃ ││
││ ━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━ ││
││ 22:45:59 │ stop nobody │ Process 'nobody' not found │ ✗ ││
││ 22:45:55 │ (result) │ Error: Process 'report-writer': Cannot transition │ ✗ ││
││ │ │ from 'running' to 'starting'. Allowed targets: │ ││
││ │ │ ['awaiting', 'failed', 'stopping', 'suspended'] │ ││
││ 22:45:55 │ start report-writer │ Starting report-writer... │ ✓ ││
││ 22:45:51 │ resume pipeline-watcher │ Resuming pipeline-watcher... │ ✓ ││
││ 22:45:45 │ status pipeline-watcher │ pipeline-watcher: state=suspended, invocations=3, │ ✓ ││
││ │ │ queue=0 │ ││
││ 22:45:40 │ suspend pipeline-watcher │ Suspending pipeline-watcher... │ ✓ ││
││ 22:45:21 │ inject report-writer │ Injected event into report-writer │ ✓ ││
││ │ {"topic": "weekly │ │ ││
││ │ numbers"} │ │ ││
││ 22:45:15 │ help │ Commands: status, start <name>, stop <name>, │ ✓ ││
││ │ │ restart <name>, suspend <name>, resume <name>, │ ││
││ │ │ inject <name> <payload>, list, help │ ││
│╰────────────────────────────────────────────────────────────────────────────────────────────────────╯│
╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯
← → Navigate 1-7 Jump Tab Next : Command Ctrl+C QuitThe history is newest first. Lifecycle commands are submitted to the runtime's event loop and show Starting report-writer... at once; when the action then fails, a (result) entry with the error follows, as it did for start on a process that was already running. status and list answer from the dashboard's snapshot. While the pipeline watcher was suspended, the Processes tab showed it in yellow. This capture is 104 columns wide, so the name column is hidden; ecd2bb4a is the pipeline watcher's process ID:
│ │ SUSPENDED │ ecd2bb4a ││ 3 │ 0 │ 1 │ 0 │ 1 │ 10s │ 1m 28s │
│ │ RUNNING │ 5c1ee5f0 ││ 1 │ 0 │ 1 │ 0 │ 1 │ 10s │ 1m 28s │A suspended process keeps queueing trigger events and runs them after resume. Pause and resume an AI agent covers suspension.
Before 1.5.0 these commands were recorded but never ran: they were scheduled on a new event loop that nothing ran. Now they run on the loop dashboard.start() captures, which is why start() must be called from the runtime's loop when you build your own dashboard.
[10]
Step 6: Embed the dashboard in your own program
When you build the runtime in Python, for example to add callback hooks or guardrails, you can still use the dashboard. Create the collector and start the dashboard inside the coroutine that runs the runtime:
"""Your own runtime program with the terminal dashboard (no control API, no state file)."""
import asyncio
from promptise.runtime import (
AgentRuntime,
RuntimeDashboard,
RuntimeDashboardState,
RuntimeDataCollector,
)
async def main() -> None:
runtime = AgentRuntime()
names = await runtime.load_directory("agents")
state = RuntimeDashboardState(runtime_name="ops (embedded)", manifest_names=names)
collector = RuntimeDataCollector(runtime, state, interval=1.0) # created on the runtime's loop
dashboard = RuntimeDashboard(state, runtime=runtime)
collector.start()
dashboard.start() # call it on the runtime's loop, so dashboard commands can run
try:
await runtime.run_forever() # starts every process; returns on Ctrl+C or SIGTERM
finally:
dashboard.stop() # restore the terminal
collector.stop() # and remove the collector's hooks
if __name__ == "__main__":
asyncio.run(main())run_forever() starts every process and returns on Ctrl+C or SIGTERM after stopping them. The finally block restores the terminal and removes the collector's hooks. Run it, and the same dashboard appears with your title. Commands work because both objects were created on the runtime's loop. Two screens of one run, the Overview header and the command history after :list:
│ █████ ██████ Runtime ops (embedded) │
…
││ Time ┃ Command ┃ Result ┃ ││
││ ━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━ ││
││ 22:43:41 │ list │ Processes: pipeline-watcher, report-writer │ ✓ ││This program has no control API and no state file, so promptise runtime status won't see it. Add an OrchestrationAPI if you need one. RuntimeDataCollector(runtime, state, interval=..., loop=...) takes the loop explicitly if you create it elsewhere; without a loop, the journal panel stays empty. state.record_invocation(), record_event() and record_journal() add records of your own.
[11]
Running it in production
Look, don't host
The dashboard runs in the runtime's own process and needs a terminal, so it ties the runtime's life to your session: Ctrl+C or a closed SSH connection stops every agent. On a server, run the runtime under a supervisor without --dashboard, and use promptise runtime status and logs --follow from an SSH session. If you want the dashboard on a server, start the runtime inside tmux or screen so a dropped connection doesn't end it.
Mind what the screen shows
Secret values from scoped secrets are redacted in the Context tab, but other state values, log records and journal data appear as they are. Don't share a screen or a recording of a dashboard that shows customer data or tool results you wouldn't log.
Keep the refresh cost low
The collector reads every process twice a second and the journal every two seconds. That is cheap for a few processes. For many processes, or a slow journal backend, build the dashboard yourself with RuntimeDataCollector(..., interval=2.0).
[12]
Common problems and fixes
Symptom | Cause | Fix |
|---|---|---|
| The dashboard draws in the foreground terminal | Drop --detach, or use status and logs for a detached runtime |
Processes tab has no Name or Model column | The table needs about 170 columns | Widen the terminal, or read names on the Overview tab |
Journal Entries panel never appears | The log panel above it fills the screen | Use a very tall terminal, or |
Logs tab full of httpcore debug lines | The dashboard sets the root logger to DEBUG while it runs | Read the promptise.runtime lines; the HTTP lines are normal |
A command shows Starting ... but nothing changes | The action failed on the event loop | Look for the (result) entry with the error below it |
Commands answer with an error in your own program | dashboard.start() was called off the runtime's loop | Create the collector and start the dashboard inside the coroutine that runs the runtime |
The terminal is garbled after a crash | dashboard.stop() didn't run | Call it in a finally block; run reset to repair the terminal |
[13]
How is it different from promptise run --tui?
Both are Promptise terminal UIs, and they answer different questions:
Runtime dashboard | promptise run --tui | |
|---|---|---|
Watches | Long-running processes in an AgentRuntime, from .agent manifests | One run of your Python program and every agent it builds |
Start it with |
| promptise run --tui in a project with promptise.toml |
Built on | rich | textual |
Tabs | Overview, Processes, Triggers, Context, Logs, Events, Commands | Console or Chat, Trace, Tools, Metrics, Events, Approvals, Agents, MCP, Logs, Run |
Detail level | Per process and per run: state, triggers, context, outcome and duration | Per call: every LLM call and tool call with arguments, results, tokens, latency and cost |
Controls | Start, stop, restart, suspend, resume, inject | Restart or stop the program, approve or deny tool calls, chat with the agent |
Other terminals | promptise runtime status, logs and the control API keep working | None |
Use --tui while you build and debug an agent's reasoning and tools; run, debug and deploy an AI agent shows it. Use the runtime dashboard once agents run on triggers and you care about their schedule, state and failures.
[14]
Limitations
Local and live only. No history beyond the ring buffers, no alerts, no browser or remote view.
No scrolling or filtering. Each tab shows the newest rows that fit; the Logs tab can't filter by level or process.
Fixed layout. Wide tables need wide terminals, and the journal panel needs a tall one.
No token or cost figures. For per-call cost and latency, use promptise run --tui or an observability backend.
Configured triggers only. Triggers an open-mode agent adds for itself don't appear in the Triggers tab.
No quit key. Ctrl+C is the only way out, and it stops every process in the runtime.
[15]
Frequently asked questions
How do I monitor AI agents in real time?
For agents in a Promptise runtime, start them with promptise runtime start agents/ --dashboard. The dashboard shows each process's state, trigger fire counts, context state, recent runs with their outcome and duration, and captured logs, refreshed four times a second. For production, combine the control API, health monitoring and an observability backend.
Can I use the dashboard with agents running in the background?
No. The dashboard needs a foreground terminal, so --dashboard can't be combined with --detach. For a background runtime, use promptise runtime status and promptise runtime logs <process> --follow, which read the same data through the state file and the journal.
What is the difference between the runtime dashboard and promptise run --tui?
The runtime dashboard watches long-running processes started from .agent manifests: their states, triggers, context and runs. promptise run --tui watches one run of a Python program in detail: every LLM call and tool call with tokens, cost and latency, plus approvals and a chat. Use the first for scheduled agents and the second to debug an agent's behavior.
How do I pause an AI agent from the dashboard?
Press : and type suspend <process name>, then Enter. The process turns yellow as SUSPENDED, and its triggers keep queueing events. Type resume <process name> to continue; the queued events then run.
Does the dashboard show secrets?
Secret values from the process's scoped secrets are replaced with [REDACTED] in the Context tab, as in the journal. Other context values, log messages and journal data are shown as they are, so treat the screen like a log viewer.
Why did dashboard commands do nothing in older versions?
Before Promptise 1.5.0, the dashboard scheduled commands on a new event loop that never ran, so they were recorded but had no effect, and the Events and journal panels stayed empty. 1.5.0 runs commands on the runtime's loop and fills those panels through lifecycle hooks and journal reads. Upgrade with pip install -U "promptise>=1.5.0".
[16]
Next steps
Start, stop and inspect runtimes from any terminal: AI agent CLI.
Write the manifests the dashboard loads: AI agent manifest.
Catch silent failures automatically: AI agent health monitoring.
Trace every tool call in production: AI agent observability.
Reference: runtime dashboard and runtime CLI in the Promptise docs.