Skip to content

How to Use DeerFlow from Claude Code with the claude-to-deerflow Skill

Problem

I was working in Claude Code and needed to do research on a new library. I had to:

  1. Leave Claude Code terminal
  2. Open DeerFlow web interface
  3. Type my research question
  4. Wait for the response
  5. Copy the results back to Claude Code

This context switching was frustrating. Every time I needed DeerFlow’s research capabilities, I lost my flow. I wondered: could I just call DeerFlow directly from Claude Code?

What I Found

I discovered the claude-to-deerflow skill in the DeerFlow repository. It lets Claude Code communicate with a running DeerFlow instance through HTTP calls.

The architecture looks like this:

┌─────────────┐ ┌──────────────────┐ ┌─────────────┐
│ Claude Code │────────▶│ claude-to-deerflow│────────▶│ DeerFlow │
│ Terminal │◀────────│ Skill │◀────────│ Agent │
└─────────────┘ └──────────────────┘ └─────────────┘
HTTP API

This means I can send research tasks to DeerFlow and get streaming responses without leaving my terminal.

Installation

First, I installed the skill:

Install claude-to-deerflow skill
npx skills add https://github.com/bytedance/deer-flow --skill claude-to-deerflow

I got this output:

Terminal window
Skill installed: claude-to-deerflow
Location: ~/.claude/skills/claude-to-deerflow/

Then I made sure DeerFlow was running:

Check if DeerFlow is running
curl -s http://localhost:2026/health

Expected output:

{"status": "healthy"}

First Attempt

I tried the skill in Claude Code:

/claude-to-deerflow

But I got an error:

Terminal window
Error: DEERFLOW_URL not configured
Unable to connect to DeerFlow at undefined

I realized I needed to set environment variables. I checked the skill documentation and found three options:

Environment variables for DeerFlow
export DEERFLOW_URL=http://localhost:2026
export DEERFLOW_GATEWAY_URL=http://localhost:2026
export DEERFLOW_LANGGRAPH_URL=http://localhost:2026/api/langgraph

After setting these, the skill worked.

Understanding the API

The skill uses DeerFlow’s LangGraph API. I tested the basic operations manually to understand how they work.

Health Check

Check DeerFlow health
curl -s "$DEERFLOW_GATEWAY_URL/health"

Output:

{"status": "healthy", "version": "0.1.0"}

List Available Models

List available AI models
curl -s "$DEERFLOW_GATEWAY_URL/api/models"

Output:

{
"models": [
{"id": "claude-3-5-sonnet", "name": "Claude 3.5 Sonnet"},
{"id": "gpt-4o", "name": "GPT-4o"}
]
}

List Available Skills

List DeerFlow skills
curl -s "$DEERFLOW_GATEWAY_URL/api/skills"

List Available Agents

List DeerFlow agents
curl -s "$DEERFLOW_GATEWAY_URL/api/agents"

Sending Messages to DeerFlow

The core functionality is sending messages and receiving streaming responses. This took me a few tries to get right.

Step 1: Create a Thread

Create a conversation thread
curl -s -X POST "$DEERFLOW_LANGGRAPH_URL/threads" \
-H "Content-Type: application/json" \
-d '{}'

Output:

{"thread_id": "abc123-def456-ghi789"}

Step 2: Send a Message with Streaming

Send message to DeerFlow agent
curl -s -N -X POST "$DEERFLOW_LANGGRAPH_URL/threads/abc123-def456-ghi789/runs/stream" \
-H "Content-Type: application/json" \
-d '{
"assistant_id": "lead_agent",
"input": {
"messages": [
{
"type": "human",
"content": [{"type": "text", "text": "Research the latest features in Python 3.12"}]
}
]
},
"stream_mode": ["values", "messages-tuple"],
"context": {
"thinking_enabled": true,
"is_plan_mode": true,
"subagent_enabled": false
}
}'

The response comes as Server-Sent Events (SSE):

event: metadata
data: {"run_id": "run-xyz789"}
event: values
data: {"messages": [...]}
event: messages-tuple
data: {"type": "ai", "content": "Python 3.12 includes several new features..."}
event: end
data: {}

Step 3: Parse the Response

To get the final response, I need to:

  1. Find the last event: values block
  2. Parse the data JSON
  3. Get the last message with type: "ai"
  4. Extract the content field

Execution Modes

DeerFlow supports different execution modes through the context parameter:

┌────────────┬──────────────────┬───────────────┬──────────────────┬─────────────────────────┐
│ Mode │ thinking_enabled │ is_plan_mode │ subagent_enabled │ Use Case │
├────────────┼──────────────────┼───────────────┼──────────────────┼─────────────────────────┤
│ Flash │ false │ false │ false │ Quick questions │
│ Standard │ true │ false │ false │ Normal tasks │
│ Pro │ true │ true │ false │ Complex planning │
│ Ultra │ true │ true │ true │ Multi-agent research │
└────────────┴──────────────────┴───────────────┴──────────────────┴─────────────────────────┘

Flash Mode (Quick Questions)

Flash mode context
{
"thinking_enabled": false,
"is_plan_mode": false,
"subagent_enabled": false
}

Pro Mode (Complex Planning)

Pro mode context
{
"thinking_enabled": true,
"is_plan_mode": true,
"subagent_enabled": false
}

Ultra Mode (Multi-Agent Research)

Ultra mode context
{
"thinking_enabled": true,
"is_plan_mode": true,
"subagent_enabled": true
}

Managing Threads

Threads persist conversation history. I can retrieve them later.

Get Thread History

Get conversation history
curl -s "$DEERFLOW_LANGGRAPH_URL/threads/abc123-def456-ghi789/history"

List All Threads

List all conversation threads
curl -s -X POST "$DEERFLOW_LANGGRAPH_URL/threads/search" \
-H "Content-Type: application/json" \
-d '{"limit": 20}'

Uploading Files for Analysis

DeerFlow can analyze uploaded files:

Upload file to DeerFlow
curl -s -X POST "$DEERFLOW_GATEWAY_URL/api/threads/abc123-def456-ghi789/uploads" \
-F "files=@/path/to/document.pdf"

Common Issues I Encountered

Issue 1: Connection Refused

When I tried to connect, I got:

Terminal window
curl: (7) Failed to connect to localhost port 2026

This meant DeerFlow wasn’t running. I started it:

Start DeerFlow
cd deer-flow
python -m deer_flow --port 2026

Issue 2: Wrong API Endpoint

I initially used the wrong endpoint:

Wrong endpoint (returns 404)
curl -s http://localhost:2026/api/chat

The correct endpoints are:

Correct endpoints
# Gateway API
http://localhost:2026/api/models
http://localhost:2026/api/skills
http://localhost:2026/api/agents
# LangGraph API
http://localhost:2026/api/langgraph/threads
http://localhost:2026/api/langgraph/threads/{thread_id}/runs/stream

Issue 3: Malformed Message Format

My first message attempt failed:

Wrong message format
{
"messages": ["Research Python 3.12"] # Wrong: string, not object
}

The correct format requires proper message objects:

Correct message format
{
"messages": [
{
"type": "human",
"content": [{"type": "text", "text": "Research Python 3.12"}]
}
]
}

Python Integration Example

I created a helper script to simplify integration:

deerflow_client.py
import httpx
import os
DEERFLOW_LANGGRAPH_URL = os.getenv(
"DEERFLOW_LANGGRAPH_URL",
"http://localhost:2026/api/langgraph"
)
async def send_to_deerflow(message: str, mode: str = "pro"):
"""Send a message to DeerFlow and stream the response."""
# Mode configurations
context_configs = {
"flash": {
"thinking_enabled": False,
"is_plan_mode": False,
"subagent_enabled": False
},
"standard": {
"thinking_enabled": True,
"is_plan_mode": False,
"subagent_enabled": False
},
"pro": {
"thinking_enabled": True,
"is_plan_mode": True,
"subagent_enabled": False
},
"ultra": {
"thinking_enabled": True,
"is_plan_mode": True,
"subagent_enabled": True
}
}
context = context_configs.get(mode, context_configs["pro"])
async with httpx.AsyncClient(timeout=60.0) as client:
# Create thread
thread_resp = await client.post(
f"{DEERFLOW_LANGGRAPH_URL}/threads",
json={}
)
thread_id = thread_resp.json()["thread_id"]
# Stream response
async with client.stream(
"POST",
f"{DEERFLOW_LANGGRAPH_URL}/threads/{thread_id}/runs/stream",
json={
"assistant_id": "lead_agent",
"input": {
"messages": [{
"type": "human",
"content": [{"type": "text", "text": message}]
}]
},
"stream_mode": ["values", "messages-tuple"],
"context": context
}
) as response:
async for line in response.aiter_lines():
if line.startswith("data:"):
yield line[5:]

Usage:

Using the DeerFlow client
import asyncio
from deerflow_client import send_to_deerflow
async def main():
async for chunk in send_to_deerflow(
"Research the best practices for async Python",
mode="pro"
):
print(chunk)
asyncio.run(main())

Why This Integration Matters

FeatureWithout IntegrationWith claude-to-deerflow
Research while codingSwitch toolsStay in terminal
Complex workflowsManual context copyDirect delegation
File analysisUpload separatelyUpload from terminal
Persistent memorySeparate systemsShared DeerFlow memory

The main benefit is workflow continuity. When I’m coding in Claude Code and need research, I don’t break my focus. I send the task to DeerFlow and continue working while it processes.

Summary

In this post, I showed how to integrate DeerFlow with Claude Code using the claude-to-deerflow skill. The key steps are:

  1. Install the skill with npx skills add
  2. Set environment variables for DeerFlow endpoints
  3. Create threads and send messages through the LangGraph API
  4. Parse SSE streaming responses
  5. Choose the right execution mode for your task

The integration eliminates context switching between tools. DeerFlow becomes an extension of Claude Code, accessible through a single command.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments