Token导航 LogoToken导航TokenDH.com
研究检索需要联网github未标认证来源可访问许可证需确认审计通过

langgraph-execution-control语言图执行控制

Agent Skill

langgraph-execution-control 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

11,139

周安装

424

GitHub Stars

7

下载量

3,457
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:langgraph-execution-control(语言图执行控制)
来源仓库:https://github.com/jackjin1997/clawforge
仓库路径:skills/langgraph-execution-control
安装命令:
npx skills add https://github.com/jackjin1997/clawforge --skill 'LangGraph Execution Control'
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/jackjin1997/clawforge --skill 'LangGraph Execution Control'

简介

用于查找、检索和筛选相关信息。langgraph-execution-control 属于研究检索类 Skill,可作为该场景下的辅助能力补充。

  • 适合根据关键词或任务线索快速定位候选结果。
  • 可结合来源仓库和原始文档继续核验用法。
  • 安装前建议确认权限范围和维护状态。
  • 需注意是否会触发联网或文件读写操作。

SKILL.md

  1. Workflows vs Agents: Predetermined paths vs dynamic decision-making
  2. Send API: Fan-out to parallel workers (map-reduce)
  3. Interrupts: Pause for human input, resume with Command
  4. Streaming: Real-time state, tokens, and custom data
CharacteristicWorkflowAgent
Control FlowFixed, predeterminedDynamic, model-driven
PredictabilityHighLow
Use CaseSequential tasksOpen-ended problems

Workflows and Agents

class AgentState(TypedDict): messages: Annotated[list, operator.add]

model_with_tools = model.bind_tools([search])

def agent_node(state: AgentState) -> dict: return {"messages": [model_with_tools.invoke(state["messages"])]}

def tool_node(state: AgentState) -> dict: """Execute tool calls from the last AI message.""" result = [] for tc in state["messages"][-1].tool_calls: observation = tools_by_name[tc["name"]].invoke(tc["args"]) result.append(ToolMessage(content=observation, tool_call_id=tc["id"])) return {"messages": result}

def should_continue(state: AgentState): return "tools" if state["messages"][-1].tool_calls else END

agent = (StateGraph(AgentState).add_node("agent", agent_node).add_node("tools", tool_node).add_edge(START, "agent").add_conditional_edges("agent", should_continue).add_edge("tools", "agent") # Loop back after tool execution.compile())

</python>
<typescript>
ReAct agent pattern: model decides when to call tools, loop until done.

import { StateGraph, StateSchema, MessagesValue, START, END } from "@langchain/langgraph"; import { ToolMessage } from "@langchain/core/messages";

const State = new StateSchema({ messages: MessagesValue }); const modelWithTools = model.bindTools([searchTool]);

const agentNode = async (state: typeof State.State) => ({ messages: [await modelWithTools.invoke(state.messages)] });

const toolNode = async (state: typeof State.State) => ({ messages: await Promise.all( (state.messages.at(-1)?.tool_calls ?? []).map(async (tc) => new ToolMessage({ content: await searchTool.invoke(tc.args), tool_call_id: tc.id }) ) ) });

const shouldContinue = (state: typeof State.State) => state.messages.at(-1)?.tool_calls?.length ? "tools" : END;

const agent = new StateGraph(State) .addNode("agent", agentNode) .addNode("tools", toolNode) .addEdge(START, "agent") .addConditionalEdges("agent", shouldContinue) .addEdge("tools", "agent") .compile();


class OrchestratorState(TypedDict): tasks: list[str] results: Annotated[list, operator.add] summary: str

def orchestrator(state: OrchestratorState): """Fan out tasks to workers.""" return [Send("worker", {"task": task}) for task in state["tasks"]]

def worker(state: dict) -> dict: return {"results": [f"Completed: {state['task']}"]}

def synthesize(state: OrchestratorState) -> dict: return {"summary": f"Processed {len(state['results'])} tasks"}

graph = (StateGraph(OrchestratorState).add_node("worker", worker).add_node("synthesize", synthesize).add_conditional_edges(START, orchestrator, ["worker"]).add_edge("worker", "synthesize").add_edge("synthesize", END).compile())

result = graph.invoke({"tasks": ["Task A", "Task B", "Task C"]})

</python> <typescript> Fan out tasks to parallel workers using the Send API and aggregate results.

import { Send, StateGraph, StateSchema, ReducedValue, START, END } from "@langchain/langgraph";
import { z } from "zod";

const State = new StateSchema({
  tasks: z.array(z.string()),
  results: new ReducedValue(
    z.array(z.string()).default(() => []),
    { reducer: (curr, upd) => curr.concat(upd) }
  ),
  summary: z.string().default(""),
});

const orchestrator = (state: typeof State.State) => {
  return state.tasks.map((task) => new Send("worker", { task }));
};

const worker = async (state: { task: string }) => {
  return { results: [`Completed: ${state.task}`] };
};

const synthesize = async (state: typeof State.State) => {
  return { summary: `Processed ${state.results.length} tasks` };
};

const graph = new StateGraph(State)
  .addNode("worker", worker)
  .addNode("synthesize", synthesize)
  .addConditionalEdges(START, orchestrator, ["worker"])
  .addEdge("worker", "synthesize")
  .addEdge("synthesize", END)
  .compile();

Interrupts (Human-in-the-Loop)

TypeWhen SetUse Case
interrupt() (recommended)Inside node codeHuman-in-the-loop, conditional pausing. Resume with Command(resume=value)
interrupt_beforeAt compile timeDebugging only, not for HITL. Resume with invoke(None, config)
interrupt_afterAt compile timeDebugging only, not for HITL. Resume with invoke(None, config)

def review_node(state): if state["needs_review"]: user_response = interrupt({"action": "review", "data": state["draft"], "question": "Approve this draft?"}) if user_response == "reject": return {"status": "rejected"} return {"status": "approved"}

checkpointer = InMemorySaver()

graph = (StateGraph(State).add_node("review", review_node).add_edge(START, "review").add_edge("review", END).compile(checkpointer=checkpointer))

config = {"configurable": {"thread_id": "1"}} result = graph.invoke({"needs_review": True, "draft": "content"}, config)

Check for interrupt

if "interrupt" in result: print(result["interrupt"])

Resume with user decision

result = graph.invoke(Command(resume="approve"), config)

</python>
<typescript>
Pause execution for human review using dynamic interrupt and resume with Command.

import { interrupt, Command, MemorySaver, StateGraph, START, END } from "@langchain/langgraph";

const reviewNode = async (state: typeof State.State) => { if (state.needsReview) { const userResponse = interrupt({ action: "review", data: state.draft, question: "Approve this draft?" }); if (userResponse === "reject") { return { status: "rejected" }; } } return { status: "approved" }; };

const checkpointer = new MemorySaver();

const graph = new StateGraph(State) .addNode("review", reviewNode) .addEdge(START, "review") .addEdge("review", END) .compile({ checkpointer });

const config = { configurable: { thread_id: "1" } }; let result = await graph.invoke({ needsReview: true, draft: "content" }, config);

// Check for interrupt if (result.__interrupt__) { console.log(result.__interrupt__); }

// Resume with user decision result = await graph.invoke(new Command({ resume: "approve" }), config);


config = {"configurable": {"thread_id": "1"}} graph.invoke({"data": "test"}, config) # Runs until step2 graph.invoke(None, config) # Resume

</python> <typescript> Set compile-time breakpoints for debugging. Not recommended for human-in-the-loop — use interrupt() instead.

const graph = new StateGraph(State)
  .addNode("step1", step1)
  .addNode("step2", step2)
  .addEdge(START, "step1")
  .addEdge("step1", "step2")
  .addEdge("step2", END)
  .compile({
    checkpointer,
    interruptBefore: ["step2"],  // Pause before step2
  });

const config = { configurable: { thread_id: "1" } };
await graph.invoke({ data: "test" }, config);  // Runs until step2
await graph.invoke(null, config);  // Resume

Streaming

ModeWhat it StreamsUse Case
valuesFull state after each stepMonitor complete state
updatesState deltasTrack incremental updates
messagesLLM tokens + metadataChat UIs
customUser-defined dataProgress indicators

def my_node(state): writer = get_stream_writer() writer("Processing step 1...") # Do work writer("Complete!") return {"result": "done"}

for chunk in graph.stream({"data": "test"}, stream_mode="custom"): print(chunk)

</python>
<typescript>
Emit custom progress updates from within nodes using the stream writer.

import { getWriter } from "@langchain/langgraph";

const myNode = async (state: typeof State.State) => { const writer = getWriter(); writer("Processing step 1..."); // Do work writer("Complete!"); return { result: "done" }; };

for await (const chunk of graph.stream({ data: "test" }, { streamMode: "custom" })) { console.log(chunk); }


- Choose workflow vs agent pattern
- Use Send API for parallel execution
- Call `interrupt()` anywhere in nodes
- Set compile-time breakpoints
- Resume with `Command(resume=...)`
- Choose stream modes

### What You CANNOT Configure

- Interrupt without checkpointer
- Resume without thread_id
- Change Send API message-passing model

# CORRECT

class State(TypedDict): results: Annotated[list, operator.add] # Accumulates

</python> <typescript> Use ReducedValue to accumulate parallel worker results.

// WRONG: No reducer
const State = new StateSchema({ results: z.array(z.string()) });

// CORRECT
const State = new StateSchema({
  results: new ReducedValue(z.array(z.string()).default(() => []), { reducer: (curr, upd) => curr.concat(upd) }),
});

CORRECT

graph = builder.compile(checkpointer=InMemorySaver())

</python>
<typescript>
Checkpointer required for interrupt functionality.

// WRONG const graph = builder.compile();

// CORRECT const graph = builder.compile({ checkpointer: new MemorySaver() });


# CORRECT

graph.invoke(Command(resume="approve"), config)

</python> <typescript> Use Command to resume from an interrupt (regular object restarts graph).

// WRONG
await graph.invoke({ resumeData: "approve" }, config);

// CORRECT
await graph.invoke(new Command({ resume: "approve" }), config);

BETTER

def should_continue(state): if state["iterations"] > 10: return END if state["messages"][-1].tool_calls: return "tools" return END

</python>
<typescript>
Add max iterations check to prevent infinite loops.

// RISKY: Might loop forever const shouldContinue = (state) => state.messages.at(-1)?.tool_calls?.length ? "tools" : END;

// BETTER const shouldContinue = (state) => { if (state.iterations > 10) return END; return state.messages.at(-1)?.tool_calls?.length ? "tools" : END; };


# CORRECT

def node(state): response = model.invoke(state["messages"]) return {"messages": [response]}

</python> </fix-messages-mode-requires-llm>

<fix-custom-mode-needs-stream-writer> <python> Use get_stream_writer() to emit custom data.

# WRONG: print() isn't streamed
def node(state):
    print("Processing...")
    return {"data": "done"}

# CORRECT
def node(state):
    writer = get_stream_writer()
    writer("Processing...")  # Streamed!
    return {"data": "done"}

CORRECT

graph.stream({}, stream_mode=["updates", "messages"])

</python>
</fix-stream-modes-are-lists>

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

39.5%
按下载量换算1,366

Claude

30.13%
按下载量换算1,042

Cursor

18.13%
按下载量换算627

Gemini CLI

9.16%
按下载量换算317

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills