Daemion docs

How do I create an action extension?

An action extension is a contextual button that appears on individual turns in the chat UI. When tapped, it dispatches a handler prompt — giving you one-tap access to operations like regenerating a response, summarizing a turn, or translating content.


When would I use an action?

Use an action when you want a repeatable operation scoped to a single turn rather than a whole thread. Good candidates:

  • Regenerate — re-run an assistant turn with a different approach
  • Summarize — condense a long assistant response into bullet points
  • Translate — convert an assistant turn into another language
  • Copy as Markdown — format a turn for pasting elsewhere
  • Explain this — ask the agent to break down its own reasoning

Actions are not for long-running autonomous work — use a job extension for that. They are not for thread-level commands — use a command extension for those.


How do I create one by chatting?

Tell Daemion what per-message operation you want. The agent writes the extension record:

You: Create an action that regenerates any assistant message

Daemion: I’ll add a Regenerate action to assistant turns.

Done — you’ll see a regenerate button on every assistant message. Tapping it will ask me to try a different approach to the same question. Want to restrict it to only the last message, or keep it on all of them?

You: Only on the last message

Daemion: Updated — the Regenerate action now only appears on the most recent assistant turn.

The extension is live in SQLite immediately. No restart needed.


How do I create one via the API?

The API is the programmatic path — for scripts, CI pipelines, or agents creating actions at runtime. Chat is the primary path for humans.

bash
Verified

curl -X POST http://localhost:3001/extensions
-H “Authorization: Bearer $DAEMION_TOKEN”
-H “Content-Type: application/json”
-d ’{ “type”: “action”, “name”: “regenerate-message”, “description”: “Re-run the last assistant turn with a different approach.”, “definition”: { “label”: “Regenerate”, “icon”: “refresh-cw”, “appliesTo”: { “roles”: [“assistant”], “position”: “last” }, “handler”: “The user wants to regenerate this response. Please try a different approach to answer the same question — vary your structure, depth, or framing.” }, “source”: “user”, “enabled”: true }’

The gateway validates definition against ActionDefinitionSchema and returns the created extension with its assigned id.


What does the action schema look like?

Defined in src/schema/extension.ts:52-60:

typescript

// ActionDefinitionSchema — the shape of definition for type: “action” interface ActionDefinition { label: string; // button text shown in the UI, e.g. “Regenerate” icon: string; // icon name, e.g. “refresh-cw”, “copy”, “language” appliesTo: { roles?: string[]; // which turn roles show this action: “user” | “assistant” position?: “any” | “last”; // “any” = all matching turns, “last” = only most recent }; handler: string; // prompt dispatched when the action is tapped }

The top-level extension envelope (shared across all 12 types):

typescript

interface Extension { id: string; // e.g. “ext_09def789” — assigned by gateway on creation type: “action”; name: string; // unique per type, kebab-case, 1-100 chars description: string; // human-readable, max 500 chars definition: ActionDefinition; source: “built-in” | “user” | “agent” | “community”; enabled: boolean; created_at: string; // ISO 8601 updated_at: string; // ISO 8601 }


Frequently asked questions

Q What are valid values for roles?
The roles array accepts "user" and "assistant". Omit roles entirely to show the action on all turns regardless of role.
Q What is the difference between position "any" and "last"?
"any" renders the action button on every turn that matches the role filter. "last" renders it only on the most recent matching turn. Use "last" for regenerate-style actions where acting on older turns doesn't make sense.
Q What icon names can I use?
The icon field accepts icon names from the icon set used by the Daemion UI. Common values: refresh-cw, copy, language, bookmark, share, scissors, zap. Check the UI source for the full list.
Q Can an agent create actions at runtime?
Yes. POST to /extensions with source: "agent". Agent-created extensions start disabled — the user enables them.
Q How do I update or delete an action?
Use PATCH /extensions/:id to update fields or DELETE /extensions/:id to remove it. See the Extensions API for the full reference.

What can go wrong

What can go wrong

400 {"error": "validation failed"} — The definition failed ActionDefinitionSchema validation. Check that label, icon, and handler are non-empty strings, and that position (if provided) is exactly "any" or "last".

401 {"error": "unauthorized"} — The Authorization header is missing or the bearer token doesn’t match the gateway token. The token is in ~/.daemion/.gateway-token. Use $DAEMION_TOKEN in your shell.

403 {"error": "cannot disable essential extensions"} — Essential built-in actions (copy, edit, regenerate, delete) cannot be disabled.

403 {"error": "cannot delete essential extensions"} — Essential actions cannot be deleted. Create a new action with source: "user" and a different name to add custom behavior.


What’s next?