v0.0.72 - Refined wizard framing and menu hotkey display; diagnosed hardcoded Didactyl fallback causing name mismatch
This commit is contained in:
205
docs/CONTEXT.md
205
docs/CONTEXT.md
@@ -4,32 +4,26 @@ See also: [SKILLS.md](SKILLS.md) · [TOOLS.md](TOOLS.md)
|
||||
|
||||
## What Is Context?
|
||||
|
||||
Every time Didactyl talks to an LLM, it sends a **context** — the complete package of information the model needs to reason and respond. Understanding context is fundamental to understanding how Didactyl works.
|
||||
Every time Didactyl talks to an LLM, it sends a **context** — the complete package of information the model needs to reason and respond.
|
||||
|
||||
Context is not just "the prompt." It is everything the LLM receives in a single request:
|
||||
Context is not just a prompt string; it is the full request payload:
|
||||
|
||||
1. **Messages** — the conversation: system prompts, user messages, assistant responses, tool results
|
||||
2. **Tool schemas** — the JSON descriptions of every tool the LLM can call
|
||||
3. **Model parameters** — temperature, max tokens, etc.
|
||||
|
||||
The LLM sees all of this together and produces its response based on the totality of what it was given.
|
||||
1. **Messages** — system/user/assistant/tool history
|
||||
2. **Tool schemas** — JSON descriptions of callable tools
|
||||
3. **Model parameters** — model, temperature, max tokens, seed, etc.
|
||||
|
||||
---
|
||||
|
||||
## The OpenAI Chat Completion Format
|
||||
## OpenAI-Compatible Chat Format
|
||||
|
||||
Didactyl uses the OpenAI-compatible chat completion API format, which is the industry standard. Every LLM request looks like this:
|
||||
Didactyl uses OpenAI-compatible chat completions.
|
||||
|
||||
```json
|
||||
{
|
||||
"model": "claude-opus-4.6",
|
||||
"messages": [
|
||||
{"role": "system", "content": "You are Didactyl, a sovereign AI agent..."},
|
||||
{"role": "system", "content": "Admin profile: ..."},
|
||||
{"role": "user", "content": "Post a note about Bitcoin"},
|
||||
{"role": "assistant", "content": null, "tool_calls": [...]},
|
||||
{"role": "tool", "content": "{\"success\":true,...}", "tool_call_id": "..."},
|
||||
{"role": "assistant", "content": "Done! I posted your note."}
|
||||
{"role": "system", "content": "..."},
|
||||
{"role": "user", "content": "..."}
|
||||
],
|
||||
"tools": [
|
||||
{
|
||||
@@ -37,7 +31,7 @@ Didactyl uses the OpenAI-compatible chat completion API format, which is the ind
|
||||
"function": {
|
||||
"name": "nostr_post",
|
||||
"description": "Publish a Nostr event",
|
||||
"parameters": { ... }
|
||||
"parameters": {"type":"object"}
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -46,145 +40,122 @@ Didactyl uses the OpenAI-compatible chat completion API format, which is the ind
|
||||
}
|
||||
```
|
||||
|
||||
### Messages
|
||||
|
||||
Messages are an ordered array. Each message has a `role`:
|
||||
### Message Roles
|
||||
|
||||
| Role | Purpose |
|
||||
|------|---------|
|
||||
| `system` | Instructions, identity, context data — the LLM reads these but the user didn't write them |
|
||||
| `user` | What the human (or trigger event) said |
|
||||
| `assistant` | What the LLM previously said or did (including tool calls) |
|
||||
| `tool` | Results from tool executions, fed back to the LLM |
|
||||
|
||||
The LLM processes all messages in order and generates the next response.
|
||||
|
||||
### Tool Schemas
|
||||
|
||||
The `tools` array describes every tool the LLM can call. Each tool has a name, description, and JSON Schema for its parameters. The LLM uses these descriptions to decide when and how to call tools.
|
||||
|
||||
Tools are not part of the message history — they are a separate capability declaration sent alongside the messages.
|
||||
|
||||
### Model Parameters
|
||||
|
||||
Temperature, max tokens, and other settings control how the LLM generates its response. These can be set globally or overridden per-skill.
|
||||
| `system` | Instructions and injected context |
|
||||
| `user` | Input message or trigger payload |
|
||||
| `assistant` | Model responses / tool call envelopes |
|
||||
| `tool` | Tool execution results fed back to model |
|
||||
|
||||
---
|
||||
|
||||
## How Didactyl Builds Context
|
||||
## Context Assembly Model
|
||||
|
||||
Didactyl assembles context dynamically for each request. The context varies depending on what triggered the request (DM, trigger event) and which skill is active.
|
||||
Didactyl uses **skill composition by adoption order**.
|
||||
|
||||
### Context Assembly Flow
|
||||
There are no context modes.
|
||||
|
||||
### Assembly Steps
|
||||
|
||||
1. Load adopted skills from kind `10123`.
|
||||
2. Resolve adopted skills in list order.
|
||||
3. Expand each skill template variables via tools.
|
||||
4. Append resolved skill output to messages in that same order.
|
||||
5. Append live input (DM text or triggering event payload).
|
||||
6. Attach tool schemas.
|
||||
7. Apply execution parameters from trigger tags (if invoked via trigger).
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
INPUT[Input: DM message or trigger event] --> MODE{Skill context_mode?}
|
||||
|
||||
MODE -->|inject| INJECT[Start with agent soul/personality]
|
||||
INJECT --> ADD_ADMIN[Add admin identity + profile]
|
||||
ADD_ADMIN --> ADD_SKILLS[Add adopted skill instructions]
|
||||
ADD_SKILLS --> ADD_HISTORY[Add conversation history]
|
||||
ADD_HISTORY --> ADD_SKILL_INST[Append this skill instructions]
|
||||
ADD_SKILL_INST --> ADD_USER[Add user message or trigger event]
|
||||
|
||||
MODE -->|full| FULL[Start with skill template only]
|
||||
FULL --> RESOLVE[Resolve template variables via tool calls]
|
||||
RESOLVE --> ADD_USER2[Add user message or trigger event]
|
||||
|
||||
MODE -->|override| OVERRIDE[Replace soul with skill prompt]
|
||||
OVERRIDE --> ADD_ADMIN2[Add admin identity + profile]
|
||||
ADD_ADMIN2 --> ADD_SKILLS2[Add adopted skill instructions]
|
||||
ADD_SKILLS2 --> ADD_HISTORY2[Add conversation history]
|
||||
ADD_HISTORY2 --> ADD_USER3[Add user message or trigger event]
|
||||
|
||||
ADD_USER --> TOOLS[Attach tool schemas]
|
||||
ADD_USER2 --> TOOLS
|
||||
ADD_USER3 --> TOOLS
|
||||
|
||||
TOOLS --> LLM[Send to LLM]
|
||||
INPUT[Input: DM or trigger event] --> ADOPT[Load adopted skills from kind 10123]
|
||||
ADOPT --> ORDER[Resolve skills in listed order]
|
||||
ORDER --> EXPAND[Expand template variables via tools]
|
||||
EXPAND --> MESSAGES[Append resolved skill messages]
|
||||
MESSAGES --> LIVE[Append live input message/event]
|
||||
LIVE --> TOOLS[Attach tool schemas]
|
||||
TOOLS --> PARAMS[Apply runtime params from trigger tags]
|
||||
PARAMS --> LLM[Send to LLM]
|
||||
```
|
||||
|
||||
### Context Parts
|
||||
### Why Order Matters
|
||||
|
||||
These are the building blocks that get assembled into the messages array:
|
||||
- Earlier adopted skills usually establish broad behavior.
|
||||
- Later adopted skills can refine or narrow behavior.
|
||||
- If instructions conflict, prompt-order effects apply.
|
||||
|
||||
---
|
||||
|
||||
## Context Parts
|
||||
|
||||
| Part | Source | Description |
|
||||
|------|--------|-------------|
|
||||
| **Soul/Personality** | Kind 31120 event | The agent's identity, rules, and behavior instructions |
|
||||
| **Admin Identity** | Config / kind 3 | Who the admin is, their pubkey |
|
||||
| **Admin Profile** | Kind 0 event | Admin's display name, about, picture |
|
||||
| **Admin Relay List** | Kind 10002 event | Admin's preferred relays |
|
||||
| **Admin Notes** | Kind 1 events | Admin's recent public posts — gives the agent awareness of what the admin is doing |
|
||||
| **Adopted Skills** | Kind 31123/31124 events | Instructions from other adopted skills |
|
||||
| **Conversation History** | Kind 4/14 events | Recent DM exchanges between admin and agent |
|
||||
| **Skill Instructions** | Active skill content | The specific skill being executed |
|
||||
| **User Message** | DM or trigger event | The input that triggered this execution |
|
||||
| **Tool Schemas** | Tool registry | JSON descriptions of available tools (sent separately from messages) |
|
||||
|
||||
### Template Variables Are Tool Calls
|
||||
|
||||
The soul's template system uses `tool:` directives to populate context sections. Each section can specify a tool to call, and the tool's output becomes that section's content:
|
||||
|
||||
```yaml
|
||||
- section: admin_profile
|
||||
role: system
|
||||
tool: nostr_admin_profile
|
||||
skip_if_empty: true
|
||||
```
|
||||
|
||||
This calls `nostr_admin_profile`, gets the result, and inserts it as a system message. Template variables like `{{admin_profile}}` in skill templates work the same way — they resolve to tool calls. There is one unified resolution mechanism: `tools_execute()`.
|
||||
|
||||
This means new context sources are added by adding tools, not by modifying the template engine.
|
||||
| Skill templates | Adopted skill events | Core instructions assembled in order |
|
||||
| Resolved variables | Tool outputs | Runtime data inserted into templates |
|
||||
| Conversation history | DM history/events | Recent dialogue context |
|
||||
| Live input | DM or trigger event | Current request payload |
|
||||
| Tool schemas | Tool registry | Capability declaration for tool calling |
|
||||
| Runtime params | Trigger tags | LLM/tool limits for this execution |
|
||||
|
||||
---
|
||||
|
||||
## Context Modes
|
||||
## Template Variables Are Tool Calls
|
||||
|
||||
Skills control how much of the default context the LLM sees using the `context_mode` field:
|
||||
Template variables resolve through tool execution.
|
||||
|
||||
| Mode | What the LLM sees | Use case |
|
||||
|------|-------------------|----------|
|
||||
| `inject` | Everything: soul + admin context + history + skill instructions | Default. Agent stays itself, gains new knowledge. |
|
||||
| `full` | Only what the skill template provides | Focused tasks: spellcheck, translation. Minimal context = cheaper, faster. |
|
||||
| `override` | Skill replaces soul, but admin context + history still included | Different personality, same capabilities. |
|
||||
Example:
|
||||
|
||||
Most skills use `inject` (the default). `full` is for specialized tasks where you want to minimize token cost. `override` is rare.
|
||||
- `{{admin_profile}}` resolves by running `nostr_admin_profile`
|
||||
- `{{admin_notes}}` resolves by running `nostr_admin_notes`
|
||||
|
||||
Unknown variables should resolve to empty values for portability.
|
||||
|
||||
---
|
||||
|
||||
## Context for Triggered Skills
|
||||
## Trigger Runtime Parameters
|
||||
|
||||
When a trigger fires (Nostr subscription match, webhook POST, cron timer, chain completion), the context is assembled the same way as for a DM — the only difference is the user message:
|
||||
Execution controls are attached to trigger tags, not skill content:
|
||||
|
||||
| Input Source | User Message Content |
|
||||
|---|---|
|
||||
| Admin DM | The DM text |
|
||||
| Nostr subscription trigger | The matching Nostr event as JSON |
|
||||
| Webhook trigger | The HTTP POST payload as JSON |
|
||||
| Cron trigger | A synthetic event with timestamp and cron expression |
|
||||
| Chain trigger | A synthetic event with the source skill's d_tag and output |
|
||||
- `llm`
|
||||
- `max_tokens`
|
||||
- `temperature`
|
||||
- `seed`
|
||||
- `tools`
|
||||
|
||||
The LLM receives the skill instructions as system context and the triggering event as the user message, then reasons about what to do and which tools to use.
|
||||
Resolution order for a triggered run:
|
||||
|
||||
1. Start with agent defaults
|
||||
2. Apply trigger tag overrides
|
||||
3. Execute
|
||||
4. Restore defaults
|
||||
|
||||
---
|
||||
|
||||
## Triggered vs Adopted Use
|
||||
|
||||
- **Adopted skill (`10123`)**: contributes context/instructions
|
||||
- **Triggered skill**: contributes context and may supply execution overrides via tags
|
||||
|
||||
This separation keeps composition simple while allowing per-trigger runtime control.
|
||||
|
||||
---
|
||||
|
||||
## Token Budget
|
||||
|
||||
Context has a cost — every token sent to the LLM costs money and takes time. Didactyl manages this through:
|
||||
Context cost is controlled by:
|
||||
|
||||
- **Context mode selection** — `full` mode skills send minimal context
|
||||
- **Skip-if-empty sections** — template sections with no content are omitted
|
||||
- **History limits** — conversation history is capped (default: 12 turns)
|
||||
- **Skill content limits** — adopted skill instructions are truncated to prevent context overflow
|
||||
- **Per-skill model selection** — cheap models for simple tasks, expensive models for complex ones
|
||||
- Adoption-list ordering and skill count
|
||||
- Conversation-history limits
|
||||
- Skill/template truncation limits
|
||||
- Per-trigger model/runtime parameter choices
|
||||
|
||||
The `/api/context/current` and `/api/context/parts` API endpoints let you inspect exactly what context would be sent right now, including character counts and token estimates.
|
||||
Use runtime context inspection endpoints to see the exact payload before LLM calls.
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- Skills — how to define LLM execution units: [SKILLS.md](SKILLS.md)
|
||||
- Tools — what the LLM can do: [TOOLS.md](TOOLS.md)
|
||||
- API — inspect context at runtime: [API.md](API.md)
|
||||
- Skills spec: [SKILLS.md](SKILLS.md)
|
||||
- Tool catalog: [TOOLS.md](TOOLS.md)
|
||||
- API details: [API.md](API.md)
|
||||
|
||||
Reference in New Issue
Block a user