Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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 @@ -371,6 +371,8 @@ Adapters are used by both `export` and `run`. Available adapters:
| `codex` | OpenAI Codex CLI instructions (export only) |
| `kiro` | Kiro agent format (export only) |
| `gitclaw` | GitClaw agent format |
| `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