ai web

Local developer console — chat with your agent, inspect traces, explore graph data, manage sessions, and capture eval cases. Single command, opens in browser, under 100 KB of vanilla JS and CSS, zero build step.

implemented localhost:8888 Embedded in the ai binary. No separate install. Auto-connects to a running ai serve, or spawns one if none is found.

Overview

ai web is a local reverse proxy and single-page app served from the ai binary itself. It auto-detects a running ai serve instance on localhost:8080 (configurable via --a2a) and proxies all /a2a/* traffic there. If ai serve is not found and --no-serve is not set, it spawns one as a subprocess.

  Browser  localhost:8888/ui/                                                
      
        HTTP                                                                
  ai web   (reverse proxy + local APIs)                                      
      ├─ /ui/*                 embedded SPA  (HTML + JS + CSS, ~80 KB)      
      ├─ /api/web-config        mode, a2a url, debug flag, backend status   
      ├─ /api/sessions/*        local session store  (JSON files on disk)   
      ├─ /api/evals/*           eval case capture + run                     
      ├─ /api/agents/*/trace-stream    SSE live trace events                
      ├─ /api/data/*            toolbox source list + tool invocation       
      ├─ /api/prompt-diff       live system prompt diff  (when --config set)
      ├─ /a2a/*                 proxied to upstream ai serve                
      └─ /.well-known/*         proxied to upstream                         
            
                                                                            
      ai serve  localhost:8080   (A2A server, agent execution, MCP tools)    

Flags

All flags are optional. The simplest invocation is just ai web.

FlagDefaultDescription
--port int 8888 Listen port. 0 = OS-assigned. Auto-increments if default in use and --port not explicitly set.
--host string 127.0.0.1 Bind address. Use 0.0.0.0 with --token for team sharing on a LAN.
--a2a string http://localhost:8080 Upstream ai serve endpoint to proxy to.
--no-open false Don't auto-open the browser.
--no-serve false Proxy-only mode — don't auto-start ai serve if backend is unreachable.
--debug false Show the trace panel by default on load.
--restart false Shut down an existing ai web instance on the same port, then start fresh.
--token string "" Bearer token for authentication. When set, all API calls require Authorization: Bearer <token>. Can also be set via AI_WEB_TOKEN env var.
--config string agent.toml Path to agent.toml. When set, enables live system prompt diff watching.
--evals-dir string evals Directory for saved eval case YAML files.
--sessions-dir string .ai/sessions Directory for persistent session JSON files.
--no-persist false Disable session persistence — don't write session files to disk.
  solo dev (default)                                     
  $ ai web                                               
  $ ai web --debug                                       

  team sharing on LAN                                    
  $ ai web --host 0.0.0.0 --token mysecret               

  connect to a remote agent                              
  $ ai web --no-serve --a2a http://my-agent.internal:8080

  restart a stuck instance                               
  $ ai web --restart                                     

Layout

Two-panel layout: chat on the left, trace on the right. A persistent footer bar shows live token counts, running cost, and context window utilization. The trace panel collapses behind a toggle on narrow viewports. Session tabs appear above the chat area when multiple sessions are open.

┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐                                           
  ai web  ·  agent name  ·  model  ·  :8888  ·  [Chat]  [Data]  [Evals]   ● connected   
├────────────────────────────────────────────────┬─────────────────────────────────────────────────────────────────────────────────────┤                                           
  session-1  session-2 ●  +                                                             
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤                                         
                                                                                         
            CHAT PANEL                                   TRACE PANEL                      
                                                                                         
    message history · streaming response            post-run ASCII trace                  
    system prompt toggle · prompt diff              LLM call boxes                        
    inline tool call markers                        tool call nodes → click to expand     
                                                    cache hit/miss indicators             
    input box  ·  Ctrl+Enter to send                                                     
    ↑ message history                                                                   
├────────────────────────────────────────────────┴─────────────────────────────────────────────────────────────────────────────────────┤                                           
  FOOTER BAR  ·  ↑ input / ↓ output tok  ·  cost  ·  turns  ·  context utilization bar  
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘                                           

The top nav bar tabs between Chat, Data (graph/SQL explorer), and Evals (capture and run eval cases). Backend connection status is live-polled every 5 seconds.

Chat Panel

Streaming SSE response from the A2A backend. Messages are tagged by role. Tool call markers appear inline in the AI response. The system prompt is viewable via a toggle above the history; when --config is set a live diff appears automatically when the file changes. Press to cycle previous messages like shell history.

┌─────────────────────────────────────────────────────────────────────┐ 
  CHAT                  system prompt   session info  [turn 3]  
├─────────────────────────────────────────────────────────────────────┤ 
                                                                   
  you   analyze the Neo4j companies schema                        
                                                                   
  ai    I'll start by examining the graph schema. Let me query     
        the available node labels and relationship types.          
                                                                   
         · called get_schema                                        
         · analyzing 12 node types, 8 relationship types           
                                                                   
        The schema has three main clusters: Organization is the    
        central hub with edges to Article (847k), Investment       
        (320k), and Person (94k).                                  
                                                                   
  you   which companies have the most article coverage?           
                                                                   
  ai    Let me run a query...                                     
                                                                   
├─────────────────────────────────────────────────────────────────────┤ 
  ┌──────────────────────────────────────────────────────────────┐ 
   > _                                                           
  └──────────────────────────────────────────────────────────────┘ 
  Ctrl+Enter send  ·  ↑ history  ·  Ctrl+K palette               
└─────────────────────────────────────────────────────────────────────┘ 

System prompt diff. When --config agent.toml is set, a background watcher polls the file every 500 ms. If the system_prompt field changes, a unified diff appears in the system prompt toggle — useful during prompt engineering sessions.

Trace Panel

Post-run ASCII box trace rendered after each full agent response. Each LLM call is a box with model name, latency, token count, stop reason, and a collapsible input message list. Cache hits are shown inline. Tool calls appear as connector nodes between boxes. Click any tool call to open the side panel with the full query and result.

┌───────────────────────────────────────────────────────────────────────┐ 
  TRACE                                          turn 3 / 3      
├───────────────────────────────────────────────────────────────────────┤ 
                                                                  
  ── turn 1 ──────────────────────────────────────────────────   
                                                                  
  ┌─ claude-sonnet-4-6  1.4s  832 tok  stop: end_turn         ─────┐
     messages [1]                                   [expand]  
  └────────────────────────────────────────────────────────────────┘
                                                                  
  ── turn 2 ──────────────────────────────────────────────────   
                                                                  
  ┌─ claude-sonnet-4-6  2.1s  1,842 tok  stop: tool_use        ────┐
     messages [3]                                   [expand]  
    cache: hit  ·  cache_read: 1,204 tok                       
  └────────────────────────────────────────────────────────────────┘
                                                                 
  ├── get_schema ──────────────────────────────  12 node types ───┤ 
                                                                 
  ┌─ claude-sonnet-4-6  0.8s    312 tok  stop: end_turn        ────┐
     messages [5]                                   [expand]  
  └────────────────────────────────────────────────────────────────┘
                                                                  
└───────────────────────────────────────────────────────────────────────┘ 

Live trace events. The trace panel also subscribes to GET /api/agents/{id}/trace-stream via SSE. This delivers model_call_start events at inference time so the LLM box appears immediately when the model starts — not after the full response lands.

Tool Side Panel

Clicking a tool call node in the trace opens a side panel. The trace panel shows only the summary inline (tool_name → N rows). The side panel shows the full query, parameters, result with syntax highlighting, and latency. Press Escape to dismiss.

┌────────────────────────────────────────────────────────────────────────────────────────────┐ 
  CHAT                                   TOOL CALL  execute_read_query    []           
├──────────────────────────────────────┤  ├──────────────────────────────────────────────────┤ 
  ai    Let me run a coverage query.     QUERY                                        
   ├── execute_read_query  10 rows    MATCH (o:Organization)<-[:MENTIONS]-(a)     
  ai    The top 10 companies by...      WHERE NOT EXISTS { (o)<-[:HAS_SUBSIDIARY]-() }
                                          RETURN o.name, count(a) AS articles         
                                          ORDER BY articles DESC LIMIT 10             
                                                                                      
                                         RESULT  10 rows  ·  42ms                    
                                          ┌──────────────────────┬────────────┐        
                                           name                  articles           
                                          ├──────────────────────┼────────────┤        
                                           Apple Inc.            18,420             
                                           Microsoft             14,832             
                                          └──────────────────────┴────────────┘        
  ┌────────────────────────────────┐      Escape to close                             
   > _                                                                              
└──────────────────────────────────────┘  └──────────────────────────────────────────────────┘ 

Sessions

Each browser tab runs an independent session. Sessions are persisted automatically as JSON files under --sessions-dir (default .ai/sessions/) after each turn. The latest session is restored on page load. The session browser (Ctrl+K → "browse sessions") lets you search and restore past conversations.

  session tabs (above chat)                                                    

    neo4j-research  companies-analysis ●  untitled-3  +            
     (paused)       (active, turn 4)     (paused)               


  session browser  (Ctrl+K → browse sessions)                                  

  ┌──────────────────────────────────────────────────────────────┐             
    SESSIONS                                                    
  ├──────────────────────────────────────────────────────────────┤             
    ┌────────────────────────────────────────────────────────┐  
      > search sessions...                                    
    └────────────────────────────────────────────────────────┘  
                                                                
    companies-analysis  14 turns  3 min ago                    
    neo4j-research       9 turns  yesterday                    
    movie-recs-test      4 turns  2 days ago                   
                                                                
  └──────────────────────────────────────────────────────────────┘             


  persistence API  (local to ai web, not proxied to ai serve)                  

  GET    /api/sessions           list sessions (id, created_at, turns, summary)
  GET    /api/sessions/{id}      full session JSON (messages array)            
  PUT    /api/sessions/{id}      write/overwrite session  (10 MB max)          
  DELETE /api/sessions/{id}      remove session file                           

Use --no-persist to disable disk writes — sessions live in browser memory only. Session IDs are path-validated server-side to prevent directory traversal.

Data Explorer

Switch to the Data tab to explore the connected graph or SQL sources directly. Supports multiple source types (Neo4j, SQL, MongoDB, Redis, and any other mcp-toolbox source). Write queries are detected and require confirmation before execution.

┌───────────────────────────────────────────────────────────────────┐
  DATA  [ companies2 (neo4j)  ]   Schema  Cypher  Visual       
├───────────────────────────────────────────────────────────────────┤
                                                                   
  ── Cypher playground ──────────────────────────────────────  
                                                                   
  ┌───────────────────────────────────────────────────────────┐  
   MATCH (o:Organization)<-[:MENTIONS]-(a:Article)           
   RETURN o.name, count(a) AS articles                       
   ORDER BY articles DESC LIMIT 10                           
  └───────────────────────────────────────────────────────────┘  
  [ Run  Ctrl+Enter ]  ↑ query history                          
                                                                   
  RESULT  10 rows  ·  38ms                                        
  ┌──────────────────────────────┬────────────────────────────┐  
   name                          articles     
  ├──────────────────────────────┼────────────────────────────┤  
   Apple Inc.                     18,420        
   Microsoft                      14,832        
   Google                         13,291        
  └──────────────────────────────┴────────────────────────────┘  
  [Table]  [JSON]  [CSV ↓]                                       
                                                                   
└───────────────────────────────────────────────────────────────────┘

Schema view. Clicking a node label in the schema tab auto-inserts a MATCH (n:Label) RETURN n LIMIT 25 template in the query editor. Fulltext and vector indexes are listed separately.

SQL sources. When the connected mcp-toolbox source is a SQL database, the playground switches to parameterized SQL with write-keyword detection (INSERT, UPDATE, DELETE, DROP, TRUNCATE) and requires explicit confirmation before execution. Results are sortable by column; CSV download is available.

Source switcher. The dropdown at the top lists all sources configured in toolbox.yaml. Switching sources reloads the schema and clears the query editor.

Eval Integration

Press Ctrl+Shift+S to save the current conversation as an eval case. A modal opens with the full conversation pre-filled so you can review and edit the expected response before saving. Cases are written as YAML to evals/ (configurable via --evals-dir). The Evals tab lets you list, run, and export cases. After a run, pass/fail badges appear inline in the chat history.

  save eval case  (Ctrl+Shift+S)                                          

  ┌──────────────────────────────────────────────────────────────────────┐
    SAVE AS EVAL CASE                                                  
  ├──────────────────────────────────────────────────────────────────────┤
    name                                                                
    ┌──────────────────────────────────────────────────────────────┐  
     neo4j-schema-coverage-ranking                                  
    └──────────────────────────────────────────────────────────────┘  
    expected output  (edit before saving)                              
    ┌──────────────────────────────────────────────────────────────┐  
      you  which companies have the most article coverage?          
      ai   Apple Inc. (18,420), Microsoft (14,832)...            
    └──────────────────────────────────────────────────────────────┘  
    → saved to  evals/neo4j-schema-coverage-ranking.yaml              
      [ Save  Ctrl+Enter ]    [ Cancel  Escape ]                     
  └──────────────────────────────────────────────────────────────────────┘


  eval markers in chat after a run                                        

    you   which companies have the most article coverage?  ✓ pass   
    you   what are the sentiment trends for Apple?         ✗ fail   


  eval YAML format                                                        

  name: neo4j-schema-coverage-ranking                                     
  input: "which companies have the most article coverage?"                
  expected_output: "Apple Inc. (18,420 articles)..."                      
  conversation:                                                           
    - role: user                                                          
      content: "which companies have the most article coverage?"          
    - role: assistant                                                     
      content: "Apple Inc. leads with 18,420 articles..."                 

Eval runs are sent to the eval sidecar at http://127.0.0.1:8093/eval/run (start with ai sidecar start eval-bridge). Results and pass/fail scores are returned per case and displayed in the Evals tab. Export all cases as a JSON array via GET /api/evals/export.

Auth & Team Sharing

By default ai web binds to 127.0.0.1 with no authentication — solo dev mode. To share with teammates on a LAN, add --host 0.0.0.0 and a --token. Team members enter the token once in the browser; it is stored in sessionStorage for the tab lifetime.

  solo dev  (default)                                    
  $ ai web                                               
    no auth  ·  binds 127.0.0.1  ·  all requests allowed

  team sharing on LAN                                    
  $ ai web --host 0.0.0.0 --token mysecret               
    Bearer token required on all /api/* endpoints       
    browser prompts once, stores in sessionStorage      
    constant-time comparison prevents timing attacks    

  env var alternative                                    
  $ AI_WEB_TOKEN=mysecret ai web --host 0.0.0.0          

  auth-exempt paths  (no token required)                 
  GET  /ui/*             static assets                   
  GET  /api/web-config   mode + connection status        
  GET  /api/health       port conflict detection         
  POST /api/reload       signal proxy reload             
  POST /api/shutdown     graceful shutdown               

CORS headers are currently echoed back for any origin, making ai web safe for loopback and LAN use. For public internet deployment, a dedicated reverse proxy with a stricter CORS policy and TLS termination is recommended.

Keyboard Shortcuts

Keyboard-first navigation — consistent with the terminal-first brand.

Shortcut Action
Ctrl+Enter / Cmd+EnterSubmit message (chat) or run query (data explorer)
Cycle previous messages in chat input (shell-style history)
Ctrl+KCommand palette — new session, browse sessions, toggle trace, clear, save eval
Ctrl+Shift+SSave current conversation as eval case
EscapeClose tool side panel / dismiss modal
  Ctrl+K command palette                                      

  ┌──────────────────────────────────────────────────────────┐
    ┌────────────────────────────────────────────────────┐  
      > _                                                 
    └────────────────────────────────────────────────────┘  
                                                           
      new session                                          
      browse sessions                                      
      toggle trace panel                                   
      clear conversation                                   
      save as eval case                                    
      view system prompt                                   
      data explorer                                        
                                                           
  └──────────────────────────────────────────────────────────┘

Local API

ai web exposes a small HTTP API on its own port for tooling and scripting. These endpoints are served locally and are distinct from the upstream A2A API on :8080.

EndpointDescription
GET /api/healthServer signature — used for port conflict detection. Returns {"server":"ai-web","port":N}.
GET /api/web-configMode, upstream A2A URL, debug flag, backend status, auth enabled flag.
GET /api/backend-statusLive connection status to ai serve. Polled every 5 s by the browser.
GET /api/prompt-diffUnified diff of system prompt since startup. Only populated when --config is set.
GET /api/sessionsList sessions (id, created_at, updated_at, turn count, summary).
GET /api/sessions/{id}Full session JSON including messages array.
PUT /api/sessions/{id}Write session (10 MB max body).
DELETE /api/sessions/{id}Delete session file.
POST /api/evalsSave eval case as YAML (512 KB max).
GET /api/evals/listList YAML files in evals directory.
POST /api/evals/runRun eval cases via eval sidecar at :8093.
GET /api/evals/exportDownload all eval cases as a JSON array.
GET /api/data/sourcesList toolbox sources (name, kind, status).
POST /api/data/toolInvoke an MCP tool directly (schema introspection or query execution).
GET /api/graph/statusWhether a graph backend is configured and reachable.
GET /api/agents/{id}/trace-streamSSE stream of live trace events for a task. Query param: task_id.
POST /api/reloadSignal the running instance to reload its proxy target.
POST /api/shutdownGraceful shutdown.