[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-a0d9f614-b67a-4bb5-a5cc-961680250dd8":3,"$frSuhq8L02kHw-jOVaQQSdS-wRIPYGT9qH1YnxW_OtTg":43},{"id":4,"title":5,"description":6,"categoryId":7,"moduleId":8,"tags":9,"prompt":10,"icon":11,"source":12,"sourceUrl":13,"authorId":14,"authorName":15,"isPublic":16,"stars":17,"runs":18,"createdAt":19,"updatedAt":19,"module":20,"category":27,"packages":34},"a0d9f614-b67a-4bb5-a5cc-961680250dd8","multi-agent-architect","使用LangGraph、LangChain和DeepAgents设计和优化适用于复杂AI工作流程的生产级多智能体系统。","cat_prod_data","mod_productivity","sickn33,productivity","---\nname: multi-agent-architect\ndescription: \"Design and optimize production-grade multi-agent systems with LangGraph, LangChain, and DeepAgents for complex AI workflows.\"\nrisk: safe\nsource: community\nmetadata:\n  category: ai-engineering\n  source_repo: pravin-python\u002Fantigravity-awesome-skills\n  source_type: community\n  date_added: \"2025-05-07\"\n  author: community\n  tags: [langgraph, langchain, multi-agent, orchestration, deepagents, rag, tool-calling]\n  tools: [claude, cursor, gemini]\n  license: \"MIT\"\n  license_source: \"https:\u002F\u002Fgithub.com\u002Fpravin-python\u002Fantigravity-awesome-skills\u002Fblob\u002Fmain\u002FLICENSE\"\n---\n\n\n# Multi-Agent Architect & Updater Skill\n\n## Overview\n\nThis skill turns Claude into a Senior AI Multi-Agent Architect specialized in LangGraph, LangChain, and DeepAgents. It provides structured workflows for creating and updating production-grade multi-agent systems — including supervisor agents, planners, researchers, coders, and memory-backed autonomous pipelines. Use it whenever you need to design, build, debug, or scale any multi-agent AI system.\n\nIf this skill adapts material from an external GitHub repository, declare both:\n\n- `source_repo: owner\u002Frepo`\n- `source_type: official` or `source_type: community`\n\n## When to Use This Skill\n\n- Use when you need to create a new agent or multi-agent workflow from scratch\n- Use when working with LangGraph state graphs, nodes, edges, or conditional routing\n- Use when the user asks about agent communication, memory systems, or tool-calling pipelines\n- Use when debugging or optimizing an existing LangChain\u002FLangGraph agent system\n- Use when architecting supervisor, planner, research, coding, or validation agent roles\n- Use when integrating DeepAgents with hierarchical planning and delegation\n\n## How It Works\n\n### Step 1: Understand the Goal\n\nBefore writing any code, clarify:\n- What is the **business objective** this agent system must achieve?\n- What **agent roles** are needed (supervisor, planner, researcher, coder, validator)?\n- What **tools** does each agent require?\n- What **memory** strategy is needed (Redis, Vector DB, LangChain Memory)?\n- What **communication protocol** connects agents (shared state, message passing)?\n\n### Step 2: Define the State Schema\n\nAll agents share a typed state object passed through the graph:\n\n```python\nfrom typing import TypedDict\n\nclass AgentState(TypedDict):\n    user_goal: str\n    tasks: list[str]\n    completed_tasks: list[str]\n    next_agent: str\n    context: dict\n    step_count: int          # guards against infinite loops\n    error: str | None\n```\n\n### Step 3: Define Agent Nodes\n\nEach agent is an **async function** that reads from state and returns an updated state:\n\n```python\nimport logging\nfrom langchain_openai import ChatOpenAI\n\nlogger = logging.getLogger(__name__)\n\nasync def research_node(state: AgentState) -> AgentState:\n    logger.info(\"research_node: starting\")\n    llm = ChatOpenAI(model=\"gpt-4o\")\n    result = await llm.bind_tools(research_tools).ainvoke(state[\"user_goal\"])\n    state[\"context\"][\"research\"] = result.content\n    state[\"next_agent\"] = \"coder\"\n    return state\n```\n\n### Step 4: Build the LangGraph\n\nWire nodes together with edges and conditional routing:\n\n```python\nfrom langgraph.graph import StateGraph, END\nfrom langgraph.prebuilt import ToolNode\n\ndef build_graph() -> StateGraph:\n    graph = StateGraph(AgentState)\n\n    graph.add_node(\"supervisor\", supervisor_node)\n    graph.add_node(\"research\",   research_node)\n    graph.add_node(\"coder\",      coding_node)\n    graph.add_node(\"validator\",  validation_node)\n    graph.add_node(\"tools\",      ToolNode(all_tools))\n\n    graph.set_entry_point(\"supervisor\")\n\n    graph.add_conditional_edges(\n        \"supervisor\",\n        route_next,\n        {\"research\": \"research\", \"coder\": \"coder\", \"end\": END}\n    )\n\n    graph.add_edge(\"research\",  \"supervisor\")\n    graph.add_edge(\"coder\",     \"validator\")\n    graph.add_edge(\"validator\", \"supervisor\")\n\n    return graph.compile()\n\ndef route_next(state: AgentState) -> str:\n    if state[\"step_count\"] > 20:\n        return \"end\"\n    return state[\"next_agent\"]\n```\n\n### Step 5: Add Memory\n\n```python\nfrom langchain_community.chat_message_histories import RedisChatMessageHistory\n\ndef get_memory(session_id: str):\n    return RedisChatMessageHistory(\n        session_id=session_id,\n        url=os.getenv(\"REDIS_URL\"),\n        ttl=3600\n    )\n```\n\n### Step 6: Run the Graph\n\n```python\nasync def run(user_goal: str, session_id: str):\n    graph = build_graph()\n    initial_state = AgentState(\n        user_goal=user_goal,\n        tasks=[],\n        completed_tasks=[],\n        next_agent=\"supervisor\",\n        context={},\n        step_count=0,\n        error=None,\n    )\n    return await graph.ainvoke(initial_state)\n```\n\n### Step 7: Expose via FastAPI (optional)\n\n```python\nfrom fastapi import FastAPI\nfrom pydantic import BaseModel\n\napp = FastAPI()\n\nclass RunRequest(BaseModel):\n    goal: str\n    session_id: str\n\n@app.post(\"\u002Frun\")\nasync def run_agent(req: RunRequest):\n    result = await run(req.goal, req.session_id)\n    return {\"result\": result}\n```\n\n---\n\n## Updating an Existing Agent\n\nWhen the user wants to update or debug an existing agent, structure the response as:\n\n```\n## Existing Issue\n[Describe the current problem]\n\n## Root Cause\n[Identify why it's happening in the architecture]\n\n## Proposed Update\n[Outline the changes at architecture level]\n\n## Updated Code\n[Generate only the changed modules]\n\n## Migration Notes\n[What breaks, what's backward-compatible]\n\n## Performance Impact\n[Latency \u002F token \u002F memory delta]\n```\n\n---\n\n## Standard Folder Structure\n\nAlways generate code in this layout:\n\n```\nmulti_agent_system\u002F\n├── agents\u002F          # One file per agent role\n├── tools\u002F           # Tool definitions and wrappers\n├── memory\u002F          # Redis, VectorDB, LangChain memory helpers\n├── prompts\u002F         # Prompt templates (one per agent)\n├── workflows\u002F       # High-level orchestration logic\n├── graphs\u002F          # LangGraph state + compiled graph definitions\n├── api\u002F             # FastAPI routes (optional)\n├── configs\u002F         # Config loader — no secrets in code\n├── tests\u002F           # Unit + integration tests per agent\n└── main.py\n```\n\n---\n\n## Examples\n\n### Example 1: Research + Coding Multi-Agent Workflow\n\n```python\n# agents\u002Fresearch_agent.py\nasync def research_node(state: AgentState) -> AgentState:\n    llm = ChatOpenAI(model=\"gpt-4o\").bind_tools([web_search, rag_search])\n    response = await llm.ainvoke(\n        f\"Research the following and return structured findings:\\n{state['user_goal']}\"\n    )\n    state[\"context\"][\"research\"] = response.content\n    state[\"next_agent\"] = \"coder\"\n    return state\n\n# agents\u002Fcoding_agent.py\nasync def coding_node(state: AgentState) -> AgentState:\n    llm = ChatOpenAI(model=\"gpt-4o\").bind_tools([python_repl, github_tool])\n    response = await llm.ainvoke(\n        f\"Given this research:\\n{state['context']['research']}\\n\\nWrite production Python code.\"\n    )\n    state[\"context\"][\"code\"] = response.content\n    state[\"next_agent\"] = \"validator\"\n    return state\n```\n\n### Example 2: Supervisor with Dynamic Delegation\n\n```python\n# agents\u002Fsupervisor_agent.py\nDELEGATION_PROMPT = \"\"\"\nYou are a supervisor. Given the current state, decide the next agent.\nAvailable agents: research, coder, validator, end.\nRespond with ONLY the agent name.\n\nGoal: {goal}\nCompleted: {completed}\nContext keys available: {context}\n\"\"\"\n\nasync def supervisor_node(state: AgentState) -> AgentState:\n    state[\"step_count\"] += 1\n    llm = ChatOpenAI(model=\"gpt-4o\")\n    decision = await llm.ainvoke(\n        DELEGATION_PROMPT.format(\n            goal=state[\"user_goal\"],\n            completed=state[\"completed_tasks\"],\n            context=list(state[\"context\"].keys()),\n        )\n    )\n    next_agent = decision.content.strip().lower()\n    # Validate against allowlist before setting\n    allowed = {\"research\", \"coder\", \"validator\", \"end\"}\n    state[\"next_agent\"] = next_agent if next_agent in allowed else \"end\"\n    return state\n```\n\n### Example 3: DeepAgents Reflection Loop\n\n```python\nasync def reflection_node(state: AgentState) -> AgentState:\n    llm = ChatOpenAI(model=\"gpt-4o\")\n    critique = await llm.ainvoke(\n        f\"Evaluate this output critically:\\n{state['context'].get('code', '')}\\n\"\n        \"List any bugs, gaps, or improvements. Be concise.\"\n    )\n    state[\"context\"][\"critique\"] = critique.content\n    state[\"next_agent\"] = \"coder\" if \"bug\" in critique.content.lower() else \"end\"\n    return state\n```\n\n---\n\n## Best Practices\n\n- ✅ One agent = one responsibility — never combine planning + coding + testing in one node\n- ✅ Use `TypedDict` for all state schemas — enables type checking and graph validation\n- ✅ Bind only the tools each agent needs — reduces hallucinated tool calls\n- ✅ Always add a `step_count` guard to prevent infinite routing loops\n- ✅ Use `async`\u002F`await` throughout — LangGraph supports async natively\n- ✅ Store all secrets in environment variables loaded via `os.getenv()`\n- ✅ Set TTLs on all Redis keys scoped to `session_id`\n- ✅ Log at every node entry and tool call for observability\n- ✅ Validate supervisor routing output against an allowlist of agent names\n- ❌ Don't hardcode API keys, model names, or Redis URLs\n- ❌ Don't share tool lists across agents that don't need them\n- ❌ Don't skip error handling — tool failures and empty LLM responses are common\n- ❌ Don't trust unvalidated LLM routing decisions — always check against an allowlist\n\n---\n\n## Limitations\n\n- This skill does not replace environment-specific testing, load testing, or security review before production deployment.\n- Generated LangGraph code targets the current stable API — always verify method signatures against your installed version (`pip show langgraph`).\n- Stop and ask for clarification if the agent's goal, tool permissions, or routing logic is ambiguous before generating a full architecture.\n- DeepAgents integration patterns assume the library is installed and configured in the target environment.\n\n---\n\n## Security & Safety Notes\n\n- Never expose API keys in generated code. All secrets must use environment variables:\n  ```python\n  OPENAI_API_KEY = os.getenv(\"OPENAI_API_KEY\")   # ✅ correct\n  OPENAI_API_KEY = \"sk-...\"                        # ❌ never do this\n  ```\n- Always validate and sanitize user inputs before injecting them into agent prompts — treat all user input as untrusted.\n- Add a permission layer before allowing agents to execute shell commands or write to filesystems.\n- If generating a Python REPL tool node, document that it must only run in a sandboxed, isolated environment.\n  \u003C!-- security-allowlist: python_repl tool examples are for sandboxed execution environments only -->\n- For production deployments, add rate-limit handling and exponential backoff on all LLM and external API calls.\n- Scope all Redis session keys to `session_id` and set a TTL to prevent memory leaks across sessions.\n\n---\n\n## Common Pitfalls\n\n- **Problem:** Agent loops indefinitely between supervisor and sub-agents  \n  **Solution:** Add `step_count: int` to state; return `\"end\"` in `route_next()` when `step_count > N`\n\n- **Problem:** Supervisor routes to a non-existent agent name  \n  **Solution:** Validate the LLM's routing output against a hardcoded allowlist before setting `next_agent`\n\n- **Problem:** Memory leaks across user sessions  \n  **Solution:** Scope Redis keys to `session_id` and always set a TTL (`ttl=3600`)\n\n- **Problem:** Tool results are ignored by the next agent  \n  **Solution:** Always write tool output into `state[\"context\"]` and confirm the next node reads it\n\n- **Problem:** Agents share too many tools and hallucinate wrong tool calls  \n  **Solution:** Use `.bind_tools([only_relevant_tools])` per agent instead of a global tool list\n\n- **Problem:** Graph fails silently on API rate limits  \n  **Solution:** Wrap LLM calls in retry logic with exponential backoff using `tenacity`\n\n---\n\n## Related Skills\n\n- `@langchain-rag` - When you need retrieval-augmented generation pipelines specifically\n- `@fastapi-backend` - When deploying agent systems as production REST APIs\n- `@python-async` - When deepening async\u002Fawait patterns used throughout agent nodes\n","","imported","https:\u002F\u002Fgithub.com\u002Fsickn33\u002Fantigravity-awesome-skills","user_system_seed","SkillOPIC",true,146,1322,"2026-05-16 13:29:48",{"id":8,"name":21,"slug":22,"icon":23,"description":24,"sort":25,"createdAt":26},"效率工具","productivity","mdi-lightning-bolt-outline","文档处理、数据分析、自动化工作流",4,"2026-05-16 12:53:40",{"id":7,"name":28,"slug":29,"icon":30,"description":31,"moduleId":8,"sort":32,"skillCount":33,"createdAt":26},"数据分析","data-analysis","mdi-chart-bar","数据可视化、统计分析",2,30,[35],{"id":36,"skillId":4,"version":37,"fileName":38,"fileSize":39,"filePath":40,"fileHash":41,"manifest":42,"createdAt":19},"9f23bd29-db7a-40a6-a97f-e9cc20af2a21","1.0.0","multi-agent-architect.zip",4796,"uploads\u002Fskills\u002Fa0d9f614-b67a-4bb5-a5cc-961680250dd8\u002Fmulti-agent-architect.zip","0b6787dc355f95bb4895bea61b07b5e236b51e4ba12fee56f18ad79c7df31e5c","[{\"path\":\"SKILL.md\",\"isDirectory\":false,\"size\":12294}]",{"code":44,"message":45,"data":46},200,"success",{"items":47,"stats":48,"page":51},[],{"averageRating":49,"totalRatings":49,"ratingCounts":50},0,[49,49,49,49,49],{"limit":52,"offset":49,"hasMore":53,"nextOffset":52,"ratedOnly":16},15,false]