Didactyl — Skills

Skill architecture, composition model, trigger types, and portability guidelines for Didactyl agents.

Didactyl — Skills

See also: CONTEXT.md · TOOLS.md

Overview

A skill is a set of instructions for the LLM stored as a Nostr event.

Skills teach the agent how to accomplish tasks — the LLM reads the instructions, reasons about them, and uses tools to take action.

Think of it like a woodshop: a skill is knowing how to carve — technique, judgment, decision-making. A tool is the chisel. The skill never directly uses the chisel without the craftsperson (the LLM) in the loop.

Skills are portable, shareable, and discoverable as Nostr events.


Skill Events

Kind Purpose Replaceable?
31123 Public skill definition Yes, by d-tag
31124 Private skill definition Yes, by d-tag
10123 Skill adoption list Yes, single per pubkey

Skill Content

Skill content is JSON and should focus on instructions, not transport/runtime controls.

{
  "kind": 31123,
  "content": {
    "description": "Check spelling and grammar",
    "template": "system:\nYou are a spelling and grammar checker.\n\nRules:\n- Fix spelling errors\n- Fix grammar errors\n- Preserve original formatting\n- Return ONLY the corrected text, no explanations\n\nuser:\n{{message}}"
  },
  "tags": [
    ["d", "spellcheck"],
    ["scope", "public"],
    ["description", "Spelling and grammar checker"]
  ]
}

Content Fields

Field Type Default Description
description string Human-readable description
template string Skill instructions/template text (recommended)
base bool false Optional hint that this skill is intended as base/default behavior

Execution parameters (llm, max_tokens, temperature, seed, tools) are defined on trigger tags, not in content.


Composition Model (No Context Modes)

Skills do not use context_mode.

Context is assembled from kind 10123 adoption list order:

  1. Resolve adopted skills in list order.
  2. Expand each skill template/tool variables.
  3. Append each resolved skill as context messages in that same order.
  4. Append live user/trigger input.

The adoption list itself is the context definition.

  • One adopted skill = single-skill behavior.
  • Multiple adopted skills = layered behavior in explicit order.
  • Reordering 10123 changes precedence naturally.

Ordering Convention

  • Earlier adopted skills generally set broader tone/policy.
  • Later adopted skills can narrow/specialize behavior.
  • If multiple skills strongly conflict, normal prompt-order effects apply.

Template Variables Are Tool Calls

Template variables are tool calls.

When the engine encounters {{admin_profile}}, it runs the corresponding tool and inserts the result into context.

Variable Tool Called Description
{{agent_identity}} agent_identity Agent identity block
{{admin_profile}} nostr_admin_profile Admin kind 0 profile
{{admin_notes}} nostr_admin_notes Admin recent notes
{{admin_relays}} nostr_admin_relays Admin relay list
{{adopted_skills}} adopted_skills Other adopted skill instructions
{{dm_history}} (expand directive) Recent DM conversation
{{message}} (built-in) Current user message
{{triggering_event}} trigger_event Triggering event JSON

Unknown variables should resolve to empty values for portability.


Triggered Skills

A triggered skill has a trigger source attached.

Didactyl trigger types:

  • nostr-subscription
  • webhook
  • cron
  • chain
  • dm

Trigger Tags

Tag Required Description
trigger Yes Trigger type: nostr-subscription, webhook, cron, chain, dm
filter Yes Type-specific filter
enabled No Whether active (default: true)
llm No Model spec fallback chain (e.g., openai/gpt-4o-mini, cheap)
max_tokens No Max output tokens for this trigger execution
temperature No Sampling temperature for this trigger execution
seed No Optional deterministic seed where supported
tools No true for all tools, false for none, or CSV list of allowed tool names

Execution Parameter Resolution

When a trigger fires:

  1. Start with agent defaults.
  2. Apply execution tags from that trigger (llm, max_tokens, temperature, seed, tools).
  3. Execute skill with those effective runtime settings.
  4. Restore defaults after the run.

Adopted vs Triggered Behavior

  • Adopted skill (10123): contributes instructions/template to context.
  • Triggered skill: contributes instructions and may define execution parameters via trigger tags.

Trigger Types

nostr-subscription

filter is a JSON-encoded Nostr subscription filter.

["trigger", "nostr-subscription"],
["filter", "{\"#p\":[\"<admin_pubkey>\"],\"kinds\":[1]}"],
["llm", "openai/gpt-4o-mini, cheap"],
["temperature", "0"],
["tools", "nostr_query,nostr_dm"],
["enabled", "true"]

webhook

filter is required and can be {}; webhook firing happens via HTTP.

["trigger", "webhook"],
["filter", "{}"],
["llm", "default"],
["tools", "true"],
["enabled", "true"]

cron

filter is a standard 5-field cron expression: minute hour day-of-month month day-of-week.

["trigger", "cron"],
["filter", "*/5 * * * *"],
["llm", "openai/gpt-4o-mini"],
["max_tokens", "300"],
["enabled", "true"]

chain

filter is the source skill d tag to chain from.

["trigger", "chain"],
["filter", "source-skill-d-tag"],
["llm", "default"],
["enabled", "true"]

dm

filter is JSON with sender scope:

  • {"from":"admin"}
  • {"from":"wot"}
  • {"from":"any"}
["trigger", "dm"],
["filter", "{\"from\":\"admin\"}"],
["llm", "default"],
["tools", "true"],
["enabled", "true"]

Private Skill Encoding (31124)

Private skills use NIP-44 encryption on event content.

Rules for kind 31124:

  • Keep d tag exposed so the event stays addressable/replaceable.
  • Move non-d metadata into plaintext payload before encryption.
  • Encrypt full payload with NIP-44 and store ciphertext in event content.
  • On receive: resolve by d, decrypt content, then read content + private tags.

Private Skill Event (on relay)

{
  "kind": 31124,
  "content": "<nip44-ciphertext>",
  "tags": [
    ["d", "mention-monitor"]
  ]
}

Decrypted Private Payload (application-level JSON)

{
  "content": {
    "description": "Monitor mentions and DM summaries",
    "template": "When {{triggering_event}} includes Bitcoin or Lightning, summarize and DM admin."
  },
  "private_tags": [
    ["scope", "private"],
    ["trigger", "nostr-subscription"],
    ["filter", "{\"#p\":[\"<admin_pubkey>\"],\"kinds\":[1]}"],
    ["llm", "openai/gpt-4o-mini, fast"],
    ["temperature", "0"],
    ["seed", "42"],
    ["tools", "nostr_query,nostr_dm"],
    ["enabled", "true"]
  ]
}

Execution Flow

sequenceDiagram
    participant Input as Message/Trigger
    participant Dispatch as Dispatcher
    participant Adopt as Adoption Resolver (10123)
    participant Ctx as Context Assembler
    participant Trig as Trigger Runtime Params
    participant LLM as LLM API

    Input->>Dispatch: message or trigger event
    Dispatch->>Adopt: load adopted skills in list order
    Adopt-->>Ctx: ordered skill templates
    Ctx->>Ctx: resolve template variables via tools
    Dispatch->>Trig: resolve trigger execution tags
    Trig-->>LLM: model + max_tokens + temperature + seed + tool policy
    Ctx->>LLM: composed messages
    LLM-->>Input: response

Limits and Safety

Limit Default Description
Max concurrent triggers 16 Prevents resource exhaustion
Trigger cooldown 60s per skill Prevents rapid-fire execution
LLM action rate limit 10/min Prevents runaway LLM costs

Storage on Nostr

Data Storage
Skills Kind 31123/31124 events
Adopted skills Kind 10123 event
Trigger definitions + execution params Tags on skill events

Portability Guidelines

To keep skills reusable across agents/clients:

  • Prefer generic instructions over implementation-specific assumptions.
  • Treat tool names as capabilities, not platform internals.
  • Resolve unknown variables safely (empty result, no hard failure).
  • Keep app-specific tags optional (["app","didactyl"]).

A skill should still be useful even when some variables/tools are unavailable.


Related Documentation

  • Tool architecture and complete tool catalog: TOOLS.md
  • Context assembly model: CONTEXT.md
  • Project overview/runtime behavior: README.md
Write a comment
No comments yet.