EpicStaff Flow Management
GitHub管理EpicStaff工作流与会话,通过CLI工具进行调试、同步和补丁操作。禁止直接调用API,需先添加命令再执行。支持读写分离及本地备份流程,确保数据序列化正确与安全。
Trigger Scenarios
Install
npx skills add EpicStaff/EpicStaff --skill EpicStaff Flow Management -g -y
SKILL.md
Frontmatter
{
"id": "epicstaff",
"name": "EpicStaff Flow Management",
"scope": [
"api",
"cli",
"integration"
],
"trigger": "always_on",
"version": 3.1,
"triggers": [
"epicstaff",
"epic-staff",
"flows",
"sessions"
],
"description": "EpicStaff flow management — inspecting, debugging, syncing, and patching flows and sessions via the epicstaff_tools.py CLI. Use this skill whenever working with EpicStaff flows, nodes, edges, connections, DTs, CDTs, sessions, crews, agents, tasks, tools, or OpenCode."
}
EpicStaff Flow Management Skill
Primary Tool
Use epicstaff_tools.py for all flow and session operations. The CLI handles DB operations, error handling, and correct serialization — things that break silently when done via raw HTTP calls.
Do not write raw urllib, requests, curl, or ad-hoc scripts against the Django API. The CLI exists because the API has subtle requirements (e.g., PATCH python_code without libraries wipes them; agent tool_ids PATCH is destructive replace). These are easy to get wrong in one-off scripts.
When you need data:
- CLI command exists → use it
- No command exists → add it to
epicstaff_tools.pyfirst, then use the CLI
File Structure
epicstaff_tools.py — CLI entry point (thin dispatcher)
common.py — Shared API helpers, constants
flows_read.py — Flow inspection, CDT read, sessions, OpenCode read
flows_write.py — Push, pull, patch, sync, rename, OpenCode abort
flows_create.py — Create new flows and nodes
tools_read.py — Tool listing and detail
tools_write.py — Pull/push tools
tools_create.py — Create new tools
projects_read.py — Crew/agent inspection
projects_write.py — Pull/push project configs
projects_create.py — Create new crews/agents/tasks
The -r Flag (Read-Only)
The -r flag marks a command as safe to auto-run without user approval. Without it, every command blocks waiting for the user to click "approve" — which makes multi-step debugging tedious.
Read-only commands: list, get, nodes, edges, connections, route-map, cdt, cdt-code, cdt-prompts, sessions, session, session-inspect, session-timings, vars, history, trace, crew-input, crews, agents, tools, tool, oc-status, oc-sessions, oc-messages, verify, export-compare, test-flow.
Write commands (push, pull, patch-*, sync-metadata, oc-abort, run-session) and create commands (create-*) require user approval — do not use -r.
The -g <GRAPH_ID> Flag
Most commands need a graph ID. Those that don't: list, sessions (optional -g), session, session-inspect, session-timings, crews (global), agents (global), tools (global), tool, crew-input, oc-status, oc-sessions, oc-messages, oc-abort, create-flow, create-tool, create-crew, create-agent, create-task, push-tools, push-project.
Exception: cdt-code skips -g when --cdt-id is provided.
Local Backups: .my_epicstaff/
Pull/push workflow uses this directory as the local working copy:
.my_epicstaff/flows/<flow_id>/— CDT code, condition groups, prompts, Python node code.my_epicstaff/tools/<flow_id>/— tool code + metadata.my_epicstaff/projects/<flow_id>/— crew, agent, task configs
Safety workflow: pull → edit locally → verify → push or patch-* → test-flow.
File naming:
cdt_<slug>_pre.py/cdt_<slug>_post.py— CDT computation codecdt_<slug>_groups.json/cdt_<slug>_prompts.json— CDT confignode_<slug>.py— Python node codewebhook_<slug>.py— Webhook node code
Configuration (.env)
Colocated with epicstaff_tools.py. Environment variables override .env:
DJANGO_PORT(default: 8000),OPENCODE_PORT(default: 4096)API_BASE_URL— full override (e.g.http://django_app:8000/apiinside Docker)
The tool resolves .my_epicstaff/ at the repo root (3 levels up from the skill directory).
Architecture Essentials
Two Data Stores
EpicStaff has two data stores that must stay in sync:
- DB (Django models) — the crew runtime reads from here
- Metadata (
Graph.metadataJSON) — the frontend reads/writes here
The push and patch-* CLI commands update both automatically. This is the main reason to always use the CLI — a raw API PATCH to a Django model won't update metadata, leaving the frontend out of sync.
DT/CDT Routing Uses Metadata Connections
_build_route_maps (in session_manager_service.py) builds the route map from metadata connections, matching DB node_name against metadata node_name to find UUIDs. If the names don't match, routing fails silently. DB edges only handle non-DT routing. Both Decision Table (DT) and Classification Decision Table (CDT) nodes use this mechanism.
Output Variables
Node output is written to variables.
Python Node Code Convention
Python nodes and Webhook nodes require a def main(...) entrypoint. The crew executor calls main() at runtime — code without it fails with name 'main' is not defined.
Python nodes: main() receives keyword arguments matching the node's input_map keys. It must return a dict that gets written to the node's output_variable_path.
def main(city="Unknown", units="celsius"):
weather = {"city": city, "temperature": 18.5, "conditions": "partly cloudy"}
return {"weather_data": weather}
Webhook nodes: main() receives the full trigger payload dict.
def main(trigger_payload=None):
body = trigger_payload.get("body", {})
city = body.get("city")
if not city:
return {"error": "Missing 'city' field", "status": 400}
return {"city": city}
The CLI warns if pushed/patched code is missing def main(. Always define it.
Critical Gotchas
init-metadatais mandatory after any structural change (create-node, create-edge, delete, rename). Without it the frontend cannot render the new nodes — they show as black dots, connections are missing, and routing breaks silently.--librariesis mandatory oncreate-node,create-webhook, andcreate-code-agent-nodefor any non-stdlib import (requests, pandas, etc.). Without it the node'slibrariesfield is empty and imports fail silently at runtime. Always include--librariesat creation time — do not usepatch-librariesas a workaround.- Node IDs change on every UI save. The frontend deletes and recreates nodes. Never hardcode DB IDs — always query first.
- Non-CDT node ports must be
null, not[]. Frontend auto-generates ports only whenports === null. - CDT prompts must be a dict, not a list.
converter_service.pycalls.items()— lists crash. - PATCH
python_codewithoutlibrarieswipes them. Always include libraries in the payload. - Agent
tool_idsPATCH is destructive replace. Include all existing tool_ids. - Session messages filter uses
session_id=(notsession=). Wrong param silently returns all rows.
Flow Creation Checklist
When creating or planning a new flow, always follow this sequence and read references/creating-flows.md for full details:
create-flow— creates the graph- Write code files first, then create nodes with
--code-fileand--librariesin one command:create-node "Process" --code-file process.py --libraries "requests,pandas"Never create empty nodes and patch later — always pass--code-file+--librariesat creation time. create-edge— wire nodes. Trigger nodes (webhook, telegram) have no input port — nothing connects TO them. When a flow has a trigger, both__start__and the trigger connect independently to the same downstream node:create-edge "__start__" "Data Enricher"(enables manual Run button)create-edge "API Intake" "Data Enricher"(webhook-triggered path) Without a__start__edge,run-sessionfails with "No node connected to start node".init-metadata— run this after every structural change, no exceptions (without it: black dots, missing connections, broken routing)- Set
__start__node variables — use DDD-style domain dicts (e.g.{"jira": {"project_key": ..., "base_url": ...}}) test-flow --verify— validate structure + file/DB/metadata sync
For EpicChat flows, also read references/epicchat.md for input_map, output_schema, and build mode setup.
When to Read Reference Files
This skill has detailed reference files for specific tasks. Read them when the situation calls for it — they're not needed for routine inspection or debugging.
| Task | Read this file |
|---|---|
| Need CLI command syntax or examples | references/commands.md |
| Creating or planning a new flow, nodes, edges, or wiring | references/creating-flows.md |
| Working with Code Agent nodes or EpicChat | references/epicchat.md |
| Debugging a failed session or API errors | references/troubleshooting.md |
Session Debugging
When asked to check sessions, use the sessions command:
- Recent sessions across all flows:
sessions -n 5 -r(no-gneeded) - Sessions for a specific flow:
sessions -g 55 -n 2 -r - Don't know the flow ID? Run
list -rfirst to see all flows with their IDs - Inspect a specific session:
session-inspect <session_id> -r - Timing breakdown:
session-timings <session_id> -r
Flags can go in any order: sessions -g 55 -n 2 -r and sessions -r -g 55 -n 2 both work.
Lessons Learned
When you discover new system behavior or encounter a recurring problem, add a note here.
- Edges use integer node IDs, not name strings. The DB stores
start_node_id/end_node_idas integers. The CLI resolves node names to IDs automatically — you still pass names likecreate-edge "__start__" "Data Enricher". Theedgescommand shows both names and IDs. Renaming a node does NOT require edge updates (IDs are stable). - Graph.metadata is no longer used (post-RC). The frontend saves
{nodes:[], connections:[]}on every UI save. Node positions are stored in each node's ownmetadataJSON field. Connections are derived from DB edges at load time. The backend runtime reads directly from DB models. Allpatch-*commands write only to DB. init-metadatasets node positions by PATCHing each node's ownmetadatafield with{position, color, icon, size}. It does NOT write toGraph.metadata.- Decision Table nodes have NO edges — only DB refs. DT outputs are wired via
condition_group.next_node_id,default_next_node_id,next_error_node_id. Useconnections(notedges) to see DT wiring. When rewiring, usepatch-dt. - Python node API endpoint is
/pythonnodes/(no hyphen). Other endpoints:/code-agent-nodes/,/crewnodes/,/llmnodes/. - DT
condition_groupsPATCH requiresconditions: []in each group. The viewset callspop("conditions")— missing key causes silent rollback. Thepatch-dtcommand auto-adds this.
Version History
- db5b17f Current 2026-07-05 19:45


