Route goalflow (wanmol/goal-flow) work — a LangGraph framework that combines workflow graphs with agent loops — into exactly one mode: fit check, transpiling a Dify DSL export into runnable LangGraph Python, authoring workflow nodes and edges, building an `agent_kit` loop with middleware and a harness, wiring the serving layer (data adapters, SSE streaming, HITL, Redis/MySQL, API-key registration), or running the pre-publish security gate. Use when the user wants Dify's visual design without Dify's runtime, a graph node that hosts an agent loop, an OpenAI-compatible wire protocol over their own workflows, or prompt-injected `SKILL.md` capabilities. Triggers on: goalflow, goal-flow, dify to langgraph, dify transpiler, dify DSL export, BaseWorkflow, agent_kit, AgentBaseNode, DataAdapter, chunk processor, HITL interrupt, dify2langgraph. Route plain graph-API questions to `langgraph-fundamentals` and `langgraph-workflow`.
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
Route goalflow (wanmol/goal-flow) work — a LangGraph framework that combines workflow graphs with agent loops — into exactly one mode: fit check, transpiling a Dify DSL export into runnable LangGraph Python, authoring workflow nodes and edges, building an `agent_kit` loop with middleware and a harness, wiring the serving layer (data adapters, SSE streaming, HITL, Redis/MySQL, API-key registration), or running the pre-publish security gate. Use when the user wants Dify's visual design without Dify's runtime, a graph node that hosts an agent loop, an OpenAI-compatible wire protocol over their own workflows, or prompt-injected `SKILL.md` capabilities. Triggers on: goalflow, goal-flow, dify to langgraph, dify transpiler, dify DSL export, BaseWorkflow, agent_kit, AgentBaseNode, DataAdapter, chunk processor, HITL interrupt, dify2langgraph. Route plain graph-API questions to `langgraph-fundamentals` and `langgraph-workflow`.
allowed-tools
Bash Read Write Edit Glob Grep
compatibility
Python 3.12, plus Redis (cache, conversation variables, stop flags) and MySQL (durable messages, HITL reviews, and the LangGraph checkpointer). `src/` layout with two packages: `goalflow` and the vendored `agent_kit`. MIT. Defaults lean toward Qwen/DashScope and Alibaba Cloud OSS because the project was extracted from an internal production system.
goalflow gives you two ways to build LLM applications on LangGraph and lets
you combine them: visual-first (design in Dify, transpile the exported DSL
into a LangGraph Python file you own) and code-first (ReAct/Deep agent
loops via the vendored agent_kit). A graph node can host an agent loop,
and an agent can call sub-workflows as tools.
Two things shape almost every answer about this project:
It is extracted from an internal production system. The generalizable
core is real; the defaults are opinionated (Qwen/DashScope, Alibaba OSS).
Its own docs open with a CAUTION: live credentials remain in git
history. That is a blocker before any public push, not a footnote.
When to use this skill
Converting a Dify flow into version-controlled LangGraph code without
staying on Dify's runtime
Choosing or authoring workflow nodes, edges, branch routing, or
iteration/loop subgraphs
Building an agent loop with agent_kit — graph builder, middleware chain,
harness/model router, executable skills
Wiring the serving layer: data adapters, SSE streaming, HITL interrupts,
Redis/MySQL, and workflow registration
Authoring SKILL.md capabilities that get LLM-matched and injected into
prompts
Auditing the repo before publishing it or deploying it anywhere real
When not to use this skill
Plain LangGraph graph/state/checkpointer API questions →
langgraph-fundamentals, langgraph-workflow, langgraph-persistence
Generic LangChain chains, retrievers, or RAG design → langchain-fundamentals,
langchain-rag
Generic HITL patterns not tied to this engine → langgraph-human-in-the-loop
deepagents used directly, outside agent_kit's wrapper → deepagents
Authoring skills for this repo's agent catalog rather than goalflow's
runtime → skill-standardization, write-a-skill
Starting artifact — a Dify DSL export, an empty repo, an existing
BaseWorkflow subclass, or a running deployment
Target shape — a workflow graph, an agent loop, or a graph node that
hosts a loop
Client protocol — Dify-native (default), OpenAI-compatible, or custom
Environment reality — is Redis and MySQL actually available? MySQL
backs the checkpointer, and the checkpointer is what makes stop/resume and
HITL work at all
Step 2: Pick exactly one mode
Mode
Use when
Produces
orient
It is unclear goalflow is the right tool
A fit verdict, or an honest route-out to plain LangGraph
transpile
A Dify DSL export exists
A generated BaseWorkflow subclass, registered and runnable
build
Authoring or fixing the graph itself
Node choices, edge/branch routing, error strategy
agent
The job is an open-ended tool-use loop
An Agent/AgentBaseNode with builder, middleware, harness
Run harden before any push to a public or shared remote, regardless of which
mode the user asked for.
Step 3: Check the environment read-only
bash .agent-skills/goalflow/scripts/goalflow.sh doctor
bash .agent-skills/goalflow/scripts/goalflow.sh doctor /path/to/goal-flow
doctor reports Python version, the core packages (langgraph, fastapi,
redis, pymysql, sqlalchemy, langchain-openai), whether goalflow and
agent_kit import, and which .env keys are set — by name only, never by
value. It installs nothing and starts no server.
Step 4: Transpile before hand-writing a graph
The transformer is a two-stage pipeline: parse the DSL into an internal graph
model, then emit Python via a double-dispatch visitor.
The parse is read-only. Host-portability rewrites happen on an in-memory
copy; your export file is never modified.
The substitution table is DifyDslParser.DEFAULT_HOST_SUBSTITUTIONS. It
encodes the original authors' internal hostnames. Pass your own
host_substitutions=, or {} to disable it — do not inherit theirs.
Generation is only half the job. A generated class does nothing until it is
registered (Step 6). Details in
references/dify-transpile.md.
Step 5: Author nodes against the real BaseNode contract
You implement exactly one method, call(self, state), and its return type
encodes both state update and routing:
Return
Meaning
dict
merge into state, continue to next_node_ids
Command(update=, goto=)
update and jump
List[str]
branch routing — pick outgoing handles
Sequence[Send]
fan out, one parallel branch per Send
None
no update
The __call__ wrapper gives you timing, logging, and a fan-in barrier for
free: a node with multiple pre_node_ids re-queues itself until its
topological depth is reached, so it runs once after all upstream branches
arrive. Do not hand-roll that.
This is a static in-code map keyed by the MD5 of the API key. Upstream
documents it as the current design and the first thing to replace for a real
deployment. MD5 is unsuitable for hashing secrets. When a user asks how to
register a workflow, answer the question and flag this — do not present it
as a production auth story.
Step 7: Prefer AgentBaseNode for agent work
AgentBaseNode multiply-inherits the workflow BaseNode and agent_kit's
Agent. Subclass it and implement output_schema, build_prompt, and
build_command. It supersedes DeepAgentBaseNode, CreateAgentBaseNode, and
StateGraphBaseNode, and it is the preferred path over the older manual
AgentNode ReAct loop.
The builder is auto-selected: DeepGraphBuilder when subagents are present,
ReactGraphBuilder otherwise. Middleware runs in list order.
references/agent-kit.md has the hooks, the
middleware catalog, and the harness/model-router contract.
Step 8: Keep protocol changes in the adapter layer
The engine emits protocol-neutral semantic events; a DataAdapter is the last
hop that serializes them. To add a protocol, implement generate() (streaming)
and execute() (blocking) — you never touch the engine, nodes, or graph.
DifyDataAdapter is an identity passthrough, because the internal format
already is the Dify protocol. OpenAIDataAdapter backs /v1/chat/completions.
Streaming is branch-aware: tokens from an untaken if-else or classifier
branch are pruned before they ever reach the client. Details in
references/serving-and-protocols.md.
Stdlib-only. It runs the upstream checklist deterministically: tracked
.env*/key/log files, .env* blobs still reachable in git history,
hard-coded internal IPs and endpoints, .gitignore coverage, LICENSE
presence, the open-CORS-with-credentials combination, the MD5 auth map, and
CodeNode's exec path. It prints one ```review fenced JSON block and
exits 1 on a blocker.
The non-negotiable rule it encodes: untracking .env does not remove it
from history. Rotate every credential and scrub history with
git filter-repo, then push to a fresh remote — never one that already
carries the secrets.
The published wanmol/goal-flow history is already scrubbed (only
.env.example survives), so this check is usually clean there. It matters for
internal forks, mirrors, and clones that predate the scrub, which is where
the original credentials still live.
Step 10: Author runtime skills with the injection cost in mind
goalflow has two skill systems. The main-project engine
(src/goalflow/skill/) matches a SKILL.md to a query with an LLM (not
keywords; default qwen-turbo, threshold 0.3, top_k 1) and injects the
Markdown body verbatim into the system prompt. agent_kit's engine adds
executable skills (module:func as a LangChain tool) and hybrid mode.
Because bodies are injected verbatim, body length is prompt cost on every
matched turn — the checker warns on oversized bodies and on the description
being too vague for the matcher to reason over.
Transpile, then own the code. The point is escaping Dify's runtime; do
not keep round-tripping through the DSL as the source of truth.
Replace the host-substitution table. Inheriting the upstream authors'
internal hostnames silently rewrites your URLs.
Never present the MD5 API-key map as production auth. Answer the
registration question, then flag it.
Treat CodeNode input as trusted-only. It execs DSL/model-provided
Python and the AST safe_check() guard is disabled upstream. Do not accept
untrusted DSLs without re-enabling and strengthening sandboxing.
Do not promise HITL or stop/resume without MySQL. The checkpointer is
the backbone of both; no checkpointer means no durable pause.
Prefer AgentBaseNode over AgentNode and over the three deprecated
bases.
Put protocol work in an adapter, never in the engine. If a change
requires touching nodes to support a client, the design has drifted.
Say when a default is Alibaba-shaped. Qwen/DashScope, OSS, and Hologres
defaults come from the project's origin, not from a recommendation.
Run preflight_audit.py before any push to a shared remote, and treat
history-resident secrets as compromised rather than merely untracked.
Examples
Example 1: "I designed a flow in Dify, now what?"
transpile mode: run the transformer, override host_substitutions, register
the generated class in the API-key map, and flag that the map is a demo
mechanism.
Example 2: "My branch's tokens leak to the client"
They should not — the chunk processor prunes untaken if-else/classifier
branches. Check whether the node provably reaches an answer/end node given
branches already taken, rather than patching the adapter.
Example 3: "Can I run this without MySQL?"
Partially, and you must say which part breaks: MySQL backs the LangGraph
checkpointer, so stop/resume and HITL stop being durable.
Example 4: "We're about to open-source our fork"
harden mode first. Run preflight_audit.py against your checkout — a
clean git status says nothing about what a clone can still recover, and a
fork that predates upstream's scrub carries the original credentials.
Example 5: "Should I use goalflow or just LangGraph?"
orient mode. If there is no Dify design to transpile, no need for a
swappable wire protocol, and no graph-hosting-a-loop requirement, plain
LangGraph is lighter — route out and say so.