skein_epic_create
Atomically create an epic and 0..50 child issues under it in a single SERIALIZABLE transaction. Use skein_epic_create when decomposing a feature, story, or chunk of work into 3+ sub-tasks that should be tracked together. Children are created in input order; each child's parentId is automatically set to the newly-allocated epic id, so child ids land as epicId.1, epicId.2, … regardless of the project's default id-generation mode. ANSWERS WITH AN ACKNOWLEDGEMENT by default — the id, the applied state and the new version, no issue card and no prose — so the expectedVersion cycle continues without a re-read; pass verbose for the full IssueDetail.
For an EMPTY epic (no children to plan up front), use the plain skein_create with type="epic" instead — this tool's value is the atomic decomposition, not the epic itself.
Atomicity: any child failure (validation, FK, race) rolls back the ENTIRE batch — the epic vanishes too. There is never a half-built decomposition on disk. A batch that lost a database serialization race after every retry (nothing written) returns serialization_retry — retry the call verbatim. On success the response is an ACKNOWLEDGEMENT, not a set of issue cards: epic and one children entry per child in input order, each carrying the identifier, the applied state and the version — enough to continue an expectedVersion cycle without re-reading — and no issue prose at all. Pass verbose for the full IssueDetail of the epic and of every child, or read one of them later with skein_show.
Children skip the layer-1 / layer-2 duplicate gate that skein_create runs by default — siblings under one epic often have legitimately similar titles ("write tests for X", "write tests for Y") and decision_required mid-decomposition would defeat the batch. The epic itself is NOT duplicate-checked either; callers wanting a duplicate-aware epic should fall back to skein_create + per-child skein_create calls.
kind is REQUIRED for agent callers (same semantics as skein_create): "directed" = user-requested, "autonomous" = agent side-quest. The value maps to source="agent_directed" / source="agent_autonomous" and propagates to every child (so the audit trail is uniform across the decomposition). Web UI callers force source=human and may omit kind.
Assignee default: without assignee, the issue is assigned to YOU (the API key's owner) and accepted, if your personal setting "Assign issues my agent creates to me" is on (the default; switch it in the web UI notification settings). Not for standing tasks, and not under someone else's parent: when the nearest assigned ancestor is another person, or one you cannot see, the issue stays unassigned. Pass unassigned: true when the user asks for an unassigned issue; to drop the assignee later, clear it with skein_update (assignee=""). Being the assignee is not a lock: skein_claim is still needed to start work. The assignee of the epic and of each child is decided separately, by its own assignee / unassigned; the epic's values do not propagate to children, and the epic created by this call counts as their parent for the someone-else's-parent rule.
Tool call template
Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.
{
"id": 1,
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"arguments": {
"project": "<project>",
"title": "<title>"
},
"name": "skein_epic_create"
}
}Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | Issue origin classification (REQUIRED for agent callers): "directed" = the human user told the agent to create this epic; "autonomous" = the agent decided to create this epic mid-task (side-quest, discovered subtask). Web UI ignores this parameter and forces source=human; MCP callers must specify it. The value propagates to every child. | |
| notes | No | Free-form notes for the epic. | |
| title | Yes | Epic title (1..1000 chars). Short, imperative — same conventions as skein_create. | |
| design | No | Design notes / approach for the epic. | |
| labels | No | Free-form labels to attach to the epic. Per-child labels go in childTemplates[i].labels — they are NOT inherited from the epic. | |
| project | Yes | Project handle: alias, name, or UUID. | |
| verbose | No | Return the full IssueDetail, prose included. Default false = acknowledgement: `id`, `ok`, `version` plus the post-state stamps that apply (`status`, `assignee`, lock / claim / close stamps) — no issue card and no free text. The version is always there, so the expectedVersion cycle needs no extra read. Details: skein_get_instructions. Applies to the epic and to every child row alike. If the write applied but its card could not be read back, the answer is the acknowledgement plus `cardUnavailable: true` — read the card with skein_show; do not repeat the write. | |
| assignee | No | For the epic. Assignee handle (username, email, or user UUID — stored verbatim, resolved on read; it resolves only to a person who may work in the project). A user UUID that does not name such a person is refused with assignee_not_allowed. Omitted or blank — your personal "Assign issues my agent creates to me" setting decides (on by default: you become the assignee, accepted), except for standing tasks and issues under someone else's parent. null counts as omitted; a non-string value (number, array, object, boolean) is refused with validation_error and nothing is created. | |
| parentId | No | Full hierarchical id of the issue the EPIC itself hangs under (e.g. "demo-42"). Omit it and the epic lands at the project root, as before. Supplying it switches the epic's own id-generation to hierarchical, so the node arrives as `<parentId>.N` instead of a project-counter id — that is the same shape skein_create(parentId=…) produces, and it is visible to skein_list(parentId=…) immediately, with no follow-up skein_reparent. Children are unaffected: their parent is always the new epic. A parent that is closed, missing, or in a project you cannot see is rejected and NOTHING is created. | |
| priority | No | Epic priority 0..4 (0=highest). Default: 3. | |
| unassigned | No | For the epic; does not propagate to children. Leave the issue without an assignee even when your personal "Assign issues my agent creates to me" setting is on. Pass it when the user asks for an unassigned issue. Cannot be combined with a non-empty `assignee`. Omitted, null or false — the setting decides. | |
| description | No | Long-form epic description (markdown). | |
| componentIds | No | Component UUIDs to attach to the epic. Must belong to the same project as the epic. Each child inherits this set by default via the existing parent-component inheritance path — supply childTemplates[i].componentIds to override per-child. | |
| sourceContext | No | Free-form annotation describing why the agent created this epic (e.g. "decomposing sk-32"). | |
| childTemplates | No | Child issues to create atomically with the epic. Each entry: {title, type?, description?, design?, acceptanceCriteria?, notes?, priority?, assignee?, unassigned?, componentIds?, labels?}. type defaults to "task"; priority defaults to 3. max 50 items per call. Children skip the duplicate-detection gate (siblings can legitimately share near-identical titles). Each child's parentId is automatically set to the new epic's id — do NOT supply it. | |
| reviewRequired | No | Whether the EPIC's author will want to review the result once it is closed. Private bookkeeping of the AUTHOR: never returned to anyone else, never shown in any feed. Omit it and your personal default applies (built-in default: true). Pass false to opt this one epic out — the usual case for a structural node that nobody reads a result from. It does NOT propagate to children: each child keeps the author's default, because the work whose result gets read lives in the children, not in the node. | |
| acceptanceCriteria | No | Acceptance criteria for the epic (markdown). |