Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,8 @@ Adapters are used by both `export` and `run`. Available adapters:
| `openclaw` | OpenClaw format |
| `nanobot` | Nanobot format |
| `cursor` | Cursor `.cursor/rules/*.mdc` files |
| `langgraph` | LangGraph `StateGraph` Python module (skills → nodes, skillflows → edges) |
| `deepagents` | LangChain DeepAgents harness (`create_deep_agent(...)`) — skills, tools, sub-agents |

```bash
# Export to system prompt
Expand Down
30 changes: 30 additions & 0 deletions examples/deepagents/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# DeepAgents example

A research agent with a fact-checker sub-agent, demonstrating the DeepAgents adapter:

- `agent.yaml` — manifest (model, skills, tools, sub-agent declaration)
- `SOUL.md` — agent identity, embedded in the generated `system_prompt`
- `skills/web-research/`, `skills/summarize/` — passed via `skills=["./skills"]`; DeepAgents loads each `SKILL.md` natively
- `tools/web-search.yaml` — emitted as a `@tool` function bound into `tools=[...]`
- `agents/fact-checker/` — emitted as a `SubAgent` dict in `subagents=[...]`
- `expected_output.py` — the Python module the adapter produces

DeepAgents is a higher-level harness on top of LangGraph — there is no graph
wiring: the model decides when to plan, when to delegate to sub-agents, and
when to call tools. If you need explicit per-step edges, use the `langgraph`
adapter instead.

## Regenerate

```bash
gapman export --dir examples/deepagents --format deepagents --output examples/deepagents/expected_output.py
```

## Run the generated agent

```bash
pip install deepagents langchain-anthropic
python examples/deepagents/expected_output.py
```

The generated file leaves tool implementations as `NotImplementedError` stubs — replace them with your own logic before invoking.
5 changes: 5 additions & 0 deletions examples/deepagents/SOUL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Research Assistant

You are a research assistant. Find authoritative sources, extract the relevant
facts, and summarize them honestly. Delegate to the `fact-checker` sub-agent
whenever a claim warrants independent verification. Cite every claim.
16 changes: 16 additions & 0 deletions examples/deepagents/agent.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
spec_version: "0.1.0"
name: research-assistant
version: 1.0.0
description: Research assistant with a fact-checker sub-agent
author: gitagent-examples
license: MIT
model:
preferred: anthropic:claude-sonnet-4-5
skills:
- web-research
- summarize
tools:
- web-search
agents:
fact-checker:
description: Verifies factual claims against authoritative sources
4 changes: 4 additions & 0 deletions examples/deepagents/agents/fact-checker/SOUL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Fact-Checker

You are a pedantic fact-checker. Treat every claim as unverified until you
locate a primary source. If a claim cannot be substantiated, say so plainly.
4 changes: 4 additions & 0 deletions examples/deepagents/agents/fact-checker/agent.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
spec_version: "0.1.0"
name: fact-checker
version: 1.0.0
description: Verifies factual claims against authoritative sources
83 changes: 83 additions & 0 deletions examples/deepagents/expected_output.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
"""
DeepAgents definition for research-assistant v1.0.0
Generated by gitagent export --format deepagents
"""

from __future__ import annotations

from deepagents import create_deep_agent
from langchain_core.tools import tool

# Agent metadata
AGENT_NAME = "research-assistant"
AGENT_VERSION = "1.0.0"
MODEL = "anthropic:claude-sonnet-4-5"

# System prompt (SOUL.md + RULES.md + DUTIES.md + compliance)
SYSTEM_PROMPT = """# research-assistant
Research assistant with a fact-checker sub-agent

# Research Assistant

You are a research assistant. Find authoritative sources, extract the relevant
facts, and summarize them honestly. Delegate to the `fact-checker` sub-agent
whenever a claim warrants independent verification. Cite every claim.
"""

# Hooks (pre_tool_use scripts run before every tool call)
def _run_pre_tool_use_hooks(tool_name: str) -> None:
"""No pre_tool_use hooks configured in hooks/hooks.yaml."""
return None

# NOTE: other hook events (post_tool_use, on_session_start, etc.) have no
# DeepAgents equivalent and are intentionally skipped.
# NOTE: memory/ has no direct DeepAgents equivalent — wire a checkpointer if needed.

# Tools (from tools/*.yaml)
@tool
def web_search(query: str) -> str:
"""Search the public web for a query"""
_run_pre_tool_use_hooks("web-search")
raise NotImplementedError("Implement tool: web-search")

TOOLS = [web_search]

# Skills (skills/<name>/SKILL.md — DeepAgents loads these natively)
# Pointing skills= at the directory lets DeepAgents discover every SKILL.md
# without us having to inline the skill content into SYSTEM_PROMPT.
SKILLS = ["./skills"]

# For reference, the skills available in this agent:
# - summarize: Condense the gathered sources into a faithful, cited summary
# - web-research: Search the web for sources relevant to the user's question

# Sub-agents (agents/<name>/ → SubAgent dicts)
fact_checker_subagent = {
"name": "fact-checker",
"description": "Verifies factual claims against authoritative sources",
"system_prompt": """# fact-checker
Verifies factual claims against authoritative sources

# Fact-Checker

You are a pedantic fact-checker. Treat every claim as unverified until you
locate a primary source. If a claim cannot be substantiated, say so plainly.
""",
"tools": TOOLS,
}

SUBAGENTS = [fact_checker_subagent]

# Agent
agent = create_deep_agent(
model=MODEL,
system_prompt=SYSTEM_PROMPT,
tools=TOOLS,
skills=SKILLS,
subagents=SUBAGENTS,
)

if __name__ == "__main__":
result = agent.invoke({"messages": [{"role": "user", "content": "Hello"}]})
for message in result["messages"]:
print(message)
8 changes: 8 additions & 0 deletions examples/deepagents/skills/summarize/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
name: summarize
description: Condense the gathered sources into a faithful, cited summary
---

Produce a concise summary of the gathered material. Every factual claim must
be attributed to a specific source URL. If sources disagree, surface the
disagreement explicitly.
8 changes: 8 additions & 0 deletions examples/deepagents/skills/web-research/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
name: web-research
description: Search the web for sources relevant to the user's question
allowed-tools: web-search
---

Use the `web-search` tool to find authoritative sources. Capture the URL of
every source consulted; downstream skills will cite them.
10 changes: 10 additions & 0 deletions examples/deepagents/tools/web-search.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: web-search
description: Search the public web for a query
input_schema:
type: object
properties:
query:
type: string
description: The search query
required:
- query
26 changes: 26 additions & 0 deletions examples/langgraph/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# LangGraph example

A two-step research agent that demonstrates the LangGraph adapter:

- `agent.yaml` — manifest (model, runtime, skill + tool references)
- `SOUL.md` — agent identity, embedded in the generated system prompt
- `skills/web-research/SKILL.md` — first node in the graph
- `skills/summarize/SKILL.md` — second node, depends on `web-research`
- `skillflows/research.yaml` — wiring (`steps`, `depends_on`) → `add_edge` calls
- `tools/web-search.yaml` — bound as a `ToolNode`
- `expected_output.py` — the Python module the adapter produces

## Regenerate

```bash
gapman export --dir examples/langgraph --format langgraph --output examples/langgraph/expected_output.py
```

## Run the generated graph

```bash
pip install "langgraph>=0.2" "langchain>=0.3" "langchain-core>=0.3" langchain-anthropic
python examples/langgraph/expected_output.py
```

The generated file leaves tool implementations as `NotImplementedError` stubs — replace them with your own logic before invoking.
4 changes: 4 additions & 0 deletions examples/langgraph/SOUL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Research Assistant

You are a research assistant. Find authoritative sources, extract the relevant
facts, and summarize them honestly. Cite every claim. When uncertain, say so.
15 changes: 15 additions & 0 deletions examples/langgraph/agent.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
spec_version: "0.1.0"
name: research-assistant
version: 1.0.0
description: Two-step research assistant — searches the web, then summarizes findings
author: gitagent-examples
license: MIT
model:
preferred: claude-sonnet-4-5
runtime:
max_turns: 25
skills:
- web-research
- summarize
tools:
- web-search
109 changes: 109 additions & 0 deletions examples/langgraph/expected_output.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
"""
LangGraph definition for research-assistant v1.0.0
Generated by gitagent export --format langgraph
"""

from __future__ import annotations

from typing import Annotated, TypedDict

from langchain_core.messages import AIMessage, BaseMessage, HumanMessage, SystemMessage
from langchain_core.tools import tool
from langchain.chat_models import init_chat_model
from langgraph.graph import END, START, StateGraph
from langgraph.graph.message import add_messages
from langgraph.prebuilt import ToolNode

# Agent metadata
AGENT_NAME = "research-assistant"
AGENT_VERSION = "1.0.0"
AGENT_DESCRIPTION = "Two-step research assistant — searches the web, then summarizes findings"
MODEL = "claude-sonnet-4-5"
RECURSION_LIMIT = 25

# System prompt (SOUL.md + RULES.md + DUTIES.md + compliance)
SYSTEM_PROMPT = """# research-assistant
Two-step research assistant — searches the web, then summarizes findings

# Research Assistant

You are a research assistant. Find authoritative sources, extract the relevant
facts, and summarize them honestly. Cite every claim. When uncertain, say so.
"""

# Skill instructions
SKILL_SUMMARIZE_INSTRUCTIONS = """Condense the gathered sources into a faithful, cited summary

Produce a concise summary of the gathered material. Every factual claim must
be attributed to a specific source URL. If the sources disagree, say so
explicitly rather than picking a side."""

SKILL_WEB_RESEARCH_INSTRUCTIONS = """Search the web for sources relevant to the user's question
Allowed tools: web-search

Use the `web-search` tool to find authoritative sources. Prefer primary sources
(official docs, academic papers) over secondary commentary. Capture the URL of
every source consulted."""

# Graph state
class AgentState(TypedDict):
messages: Annotated[list[BaseMessage], add_messages]

# Tools (from tools/*.yaml)
@tool
def web_search(query: str) -> str:
"""Search the public web for a query"""
raise NotImplementedError("Implement tool: web-search")

TOOLS = [web_search]
tool_node = ToolNode(TOOLS)

llm = init_chat_model(MODEL)
llm_with_tools = llm.bind_tools(TOOLS) if TOOLS else llm

# Hooks (pre_tool_use → before_tool callback)
def before_tool(state: AgentState) -> AgentState:
"""No pre_tool_use hooks configured in hooks/hooks.yaml."""
return state

# NOTE: post_tool_use, on_session_start, etc. have no LangGraph equivalent — skipped.
# NOTE: memory/ has no direct LangGraph equivalent — implement via a checkpointer.

# Skill nodes (one per skills/<name>/SKILL.md)
def skill_summarize(state: AgentState) -> dict:
"""Skill node: summarize — Condense the gathered sources into a faithful, cited summary"""
prompt = SYSTEM_PROMPT + "\n\n" + SKILL_SUMMARIZE_INSTRUCTIONS
messages = [SystemMessage(content=prompt), *state["messages"]]
response = llm_with_tools.invoke(messages)
return {"messages": [response]}

def skill_web_research(state: AgentState) -> dict:
"""Skill node: web-research — Search the web for sources relevant to the user's question"""
prompt = SYSTEM_PROMPT + "\n\n" + SKILL_WEB_RESEARCH_INSTRUCTIONS
messages = [SystemMessage(content=prompt), *state["messages"]]
response = llm_with_tools.invoke(messages)
return {"messages": [response]}

# Graph construction
graph = StateGraph(AgentState)

graph.add_node("tools", tool_node)

# Skillflow: research
graph.add_node("research", skill_web_research)
graph.add_node("summarize", skill_summarize)
graph.add_edge(START, "research")
graph.add_edge("research", "summarize")
graph.add_edge("summarize", END)


# Compile
app = graph.compile()

if __name__ == "__main__":
result = app.invoke(
{"messages": [HumanMessage(content="Hello")]},
config={"recursion_limit": RECURSION_LIMIT},
)
for message in result["messages"]:
print(message)
8 changes: 8 additions & 0 deletions examples/langgraph/skillflows/research.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
name: research
description: Run web-research, then summarize the result
steps:
- id: research
skill: web-research
- id: summarize
skill: summarize
depends_on: [research]
8 changes: 8 additions & 0 deletions examples/langgraph/skills/summarize/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
name: summarize
description: Condense the gathered sources into a faithful, cited summary
---

Produce a concise summary of the gathered material. Every factual claim must
be attributed to a specific source URL. If the sources disagree, say so
explicitly rather than picking a side.
9 changes: 9 additions & 0 deletions examples/langgraph/skills/web-research/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
name: web-research
description: Search the web for sources relevant to the user's question
allowed-tools: web-search
---

Use the `web-search` tool to find authoritative sources. Prefer primary sources
(official docs, academic papers) over secondary commentary. Capture the URL of
every source consulted.
10 changes: 10 additions & 0 deletions examples/langgraph/tools/web-search.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: web-search
description: Search the public web for a query
input_schema:
type: object
properties:
query:
type: string
description: The search query
required:
- query
Loading