Files
didactyl/plans/admin_web_frontend.md

9.4 KiB

Didactyl Admin Web Frontend — Project Brief

What Is Didactyl?

Didactyl is a sovereign AI agent that lives on Nostr. It connects to Nostr relays, listens for encrypted DMs from its administrator, reasons with an LLM, and takes actions — posting events, querying relays, running shell commands, managing skills. Everything the agent knows and does is stored as Nostr events.

The agent is a C binary that runs on a server. It has no web interface of its own — all interaction happens through Nostr DMs.

What We Are Building

A local web admin dashboard that connects to the running didactyl agent via a localhost HTTP API. The dashboard is a prompt crafting and agent inspection tool for the administrator.

This is not a chat interface. The administrator already chats with the agent through Nostr DMs. This dashboard is for:

  1. Inspecting what the agent sees — its full LLM context, broken into labeled parts with token counts
  2. Crafting custom prompts — editing system prompts, user messages, and context pieces
  3. Running prompts against the LLM — with or without the agent tool set
  4. Comparing prompt variants side-by-side — A/B testing different prompt wordings or models

The API

The didactyl agent exposes a localhost-only HTTP API on port 8484 by default. Full API documentation is in docs/API.md. All endpoints return JSON with CORS headers.

Base URL

http://127.0.0.1:8484

Currently Implemented Endpoints

Method Path Purpose
GET /api/status Agent runtime status — name, version, pubkey, relay count, trigger count
GET /api/context/current Full LLM context messages array with total char/token counts
GET /api/context/parts Context broken into labeled parts with individual sizes
POST /api/prompt/run-simple Simple prompt: system + user message, no tools, returns text
POST /api/prompt/run Full prompt: messages array with tools enabled, returns conversation trace
POST /api/prompt/compare A/B test: two prompt variants run sequentially, responses side-by-side
GET /api/model Current LLM model config (provider, model, base_url, max_tokens, temperature)
PUT /api/model Change model at runtime — persists to config.json
GET /api/models List available models from the configured provider

Planned Future Endpoints

These are not yet implemented but are on the roadmap:

Method Path Purpose
GET /api/config Runtime config with redacted secrets
GET /api/events/soul Agent soul/system prompt event
PUT /api/events/soul Update soul content
GET /api/events/skills List skills
GET/PUT /api/events/skills/:d_tag Read/update individual skills
GET /api/events/profile Agent Nostr profile
GET /api/tools List all tool schemas
POST /api/tools/:name/execute Execute a tool directly
GET /api/triggers Active trigger subscriptions
GET /api/relays Relay connection status

Core User Workflows

1. Context Inspector

The primary read-only workflow. The admin wants to understand what the agent sees when it processes a message.

flowchart TD
    LOAD[Load /api/context/parts] --> DISPLAY[Display parts list]
    DISPLAY --> DETAIL[Click part to expand content]
    DETAIL --> TOKENS[Show char count and token estimate per part]
    TOKENS --> TOTAL[Show total context size]

What to show:

  • A list/table of context parts with name, role, character count, estimated tokens
  • Total context size as a summary bar or header
  • Expandable content for each part
  • The parts are: system_prompt, admin_identity, admin_profile, admin_relay_list, startup_events, adopted_skills, dm_history (one entry per turn, up to limit), admin_notes
  • Part names come from the ---template--- section of the soul event (kind 31120); they may differ if the soul is customised

2. Simple Prompt Crafting

Quick iteration on prompt wording without tools.

flowchart TD
    WRITE[Write system prompt + user message] --> RUN[POST /api/prompt/run-simple]
    RUN --> RESULT[Display response text]
    RESULT --> EDIT[Edit and re-run]
    EDIT --> RUN

What to show:

  • Two text areas: system prompt, user message
  • Optional model override dropdown/input
  • Run button
  • Response display with model used and token estimates

3. Full Prompt with Tools

Craft a complete messages array and run it with the agent tool set.

flowchart TD
    CONTEXT[Load context from /api/context/parts] --> EDIT[Edit/rearrange context parts]
    EDIT --> ADD[Add user message]
    ADD --> RUN[POST /api/prompt/run]
    RUN --> TRACE[Display conversation trace]
    TRACE --> TOOLS[Show tool calls and results per turn]
    TOOLS --> FINAL[Show final response]

What to show:

  • Pre-populate from context parts or start from scratch
  • Messages editor — add/remove/reorder messages with role and content
  • Max turns slider/input
  • Optional model override
  • Run button
  • Turn-by-turn trace showing tool calls with name, arguments, and results
  • Final response text
  • Token estimates

4. A/B Prompt Comparison

Compare two prompt variants side-by-side.

flowchart TD
    CRAFT_A[Craft variant A messages] --> CRAFT_B[Craft variant B messages]
    CRAFT_B --> COMPARE[POST /api/prompt/compare]
    COMPARE --> SIDE[Display responses side-by-side]
    SIDE --> DIFF[Compare final responses and token usage]

What to show:

  • Two prompt editors side-by-side, each with messages array + model override + max turns
  • Compare button
  • Side-by-side response display
  • Highlight differences in final response text
  • Token usage comparison

5. Status Dashboard

Simple overview of agent health.

What to show:

  • Agent name, version, pubkey
  • Connected relays count vs configured
  • Active triggers count
  • API connection status indicator

Key Design Decisions

Localhost Only

The API binds to 127.0.0.1 — the frontend must run on the same machine as the agent, or use SSH tunneling. There is no authentication. This is intentional — it is a local dev/admin tool.

No WebSocket

The API is plain HTTP request/response. There is no WebSocket or streaming. Prompt execution calls may take several seconds for LLM responses — the frontend should show a loading state.

Token Estimation

All token counts from the API use a chars / 4 heuristic. This is approximate. The frontend can display these as-is or add its own tokenizer if more precision is needed.

Model Override

The model field in prompt requests temporarily overrides the agent configured model for that single request, then restores the original. This enables cross-model comparison without changing agent config.

Tool Execution Is Real

When using /api/prompt/run or /api/prompt/compare, tool calls are actually executed. If the LLM decides to post a Nostr event, it will really post it. The frontend should make this clear to the user — perhaps with a warning or confirmation before running prompts with tools enabled.


Response Shapes Quick Reference

Status

{
  "success": true,
  "name": "Didactyl",
  "version": "v0.0.26",
  "pubkey": "52a3e8...",
  "relay_count": 4,
  "connected_relays": 4,
  "active_triggers": 0
}

Context Parts

{
  "success": true,
  "total_chars": 13131,
  "total_estimated_tokens": 3283,
  "parts": [
    {
      "name": "system_prompt",
      "role": "system",
      "chars": 1200,
      "estimated_tokens": 300,
      "content": "# Didactyl Agent..."
    }
  ],
  "messages": [...]
}

Simple Prompt Response

{
  "success": true,
  "response": "ok",
  "model_used": "claude-haiku-4.5",
  "input_tokens_estimate": 10,
  "output_tokens_estimate": 1
}

Full Prompt Response

{
  "success": true,
  "final_response": "Done! I posted a tweet.",
  "turns": [
    {
      "turn": 1,
      "tool_calls": [
        {"name": "nostr_post", "arguments": "...", "result": "..."}
      ]
    }
  ],
  "model_used": "claude-haiku-4.5",
  "total_input_tokens_estimate": 3200,
  "total_output_tokens_estimate": 180
}

Compare Response

{
  "success": true,
  "variant_a": { "...same shape as full prompt response..." },
  "variant_b": { "...same shape as full prompt response..." }
}

Error Response

{
  "success": false,
  "error": "description of what went wrong"
}

Technology Suggestions

No technology is mandated for the frontend. Some reasonable choices:

  • Vanilla HTML/JS — simplest, no build step, just open in browser
  • React/Preact — if you want component structure
  • Svelte — lightweight, good for small dashboards
  • Vue — also fine

The frontend is a separate project from didactyl. It just needs to make HTTP requests to localhost:8484.


File References

File Description
docs/API.md Full API endpoint reference with request/response examples
plans/admin_api.md Original architecture plan for the HTTP API
src/http_api.c C implementation of all endpoints
src/http_api.h Public API header
config.json.example Example config showing the api section

Getting Started

  1. Ensure didactyl is running with api.enabled: true in config.json
  2. Verify the API is up: curl http://127.0.0.1:8484/api/status
  3. Build the frontend to talk to http://127.0.0.1:8484
  4. Start with the status endpoint and context inspector, then add prompt crafting