---
source_url: "https://you.com/docs/integrations/langgraph"
title: "LangGraph Integration | You.com | You.com | Documentation"
mirrored_at: 2026-08-12T01:08:34.892Z
host: you.com
cited_in_42a: true
mirror_canonical: "https://index.42a.ai/you.com/docs/integrations/langgraph"
---

> **Original source:** https://you.com/docs/integrations/langgraph

LangGraph is a framework for building stateful, multi-step agent applications as graphs. It gives you fine-grained control over agent behavior — tool routing, state management, cycles, and human-in-the-loop patterns — while staying compatible with the LangChain ecosystem.

The [`langchain-youdotcom`](https://pypi.org/project/langchain-youdotcom/) package provides `YouSearchTool` and `YouContentsTool`, which plug directly into LangGraph agents to give them real-time web access.

* * *

## Getting Started

[1](https://you.com/docs/integrations/langgraph#install-the-packages)

### Install the Packages

$

pip install -U langchain-youdotcom langgraph langchain langchain-openai

[2](https://you.com/docs/integrations/langgraph#set-your-api-keys)

### Set Your API Keys

$

export YDC\_API\_KEY\="<YDC\_API\_KEY>"

$

export OPENAI\_API\_KEY\=your\_openai\_key

Get your You.com API key at [you.com/platform](https://you.com/platform).

The examples below use OpenAI as the LLM provider, but any LangChain-compatible chat model works — Anthropic, Google, Mistral, local models, etc.

* * *

## ReAct Agent

The fastest way to get started is `create_agent`, a prebuilt LangGraph agent that handles tool calling and message routing automatically.

1

from langchain\_openai import ChatOpenAI

2

from langchain\_youdotcom import YouSearchTool, YouContentsTool

3

from langchain.agents import create\_agent

4

5

llm \= ChatOpenAI(model\="gpt-4o-mini")

6

tools \= \[YouSearchTool(), YouContentsTool()\]

7

8

agent \= create\_agent(llm, tools)

9

10

response \= agent.invoke(

11

    {"messages": \[{"role": "user", "content": "What are the top AI stories this week?"}\]}

12

)

13

print(response\["messages"\]\[\-1\].content)

### Customizing Search Parameters

Pass an `api_wrapper` to control search behavior:

1

from langchain\_youdotcom import YouSearchAPIWrapper, YouSearchTool

2

3

tool \= YouSearchTool(

4

    api\_wrapper\=YouSearchAPIWrapper(

5

        count\=5,

6

        livecrawl\="web",

7

        freshness\="day",

8

        safesearch\="moderate",

9

    )

10

)

* * *

## Streaming

LangGraph supports token-level streaming out of the box. Use `astream_events` to stream agent responses as they’re generated:

1

import asyncio

2

from langchain\_openai import ChatOpenAI

3

from langchain\_youdotcom import YouSearchTool

4

from langchain.agents import create\_agent

5

6

llm \= ChatOpenAI(model\="gpt-4o-mini")

7

agent \= create\_agent(llm, \[YouSearchTool()\])

8

9

10

async def main():

11

    async for event in agent.astream\_events(

12

        {"messages": \[{"role": "user", "content": "What is the current price of Bitcoin?"}\]},

13

        version\="v2",

14

    ):

15

        if event\["event"\] == "on\_chat\_model\_stream":

16

            token \= event\["data"\]\["chunk"\].content

17

            if token:

18

                print(token, end\="", flush\=True)

19

    print()

20

21

22

asyncio.run(main())

* * *

## Custom Graph With a Search Node

For more control, build a custom `StateGraph`. This example creates a simple search-then-summarize pipeline where the agent searches the web, then synthesizes an answer from the results:

1

from langchain\_openai import ChatOpenAI

2

from langchain\_youdotcom import YouSearchTool

3

from langgraph.graph import START, END, StateGraph, MessagesState

4

5

llm \= ChatOpenAI(model\="gpt-4o-mini")

6

search \= YouSearchTool()

7

8

9

def search\_web(state: MessagesState):

10

    """Search the web for the user's query."""

11

    user\_message \= state\["messages"\]\[\-1\].content

12

    results \= search.invoke(user\_message)

13

    return {

14

        "messages": \[

15

            {

16

                "role": "system",

17

                "content": f"Search results:\\n\\n{results}",

18

            }

19

        \]

20

    }

21

22

23

def summarize(state: MessagesState):

24

    """Summarize the search results into a final answer."""

25

    response \= llm.invoke(state\["messages"\])

26

    return {"messages": \[response\]}

27

28

29

graph \= StateGraph(MessagesState)

30

graph.add\_node("search", search\_web)

31

graph.add\_node("summarize", summarize)

32

33

graph.add\_edge(START, "search")

34

graph.add\_edge("search", "summarize")

35

graph.add\_edge("summarize", END)

36

37

app \= graph.compile()

38

39

response \= app.invoke(

40

    {"messages": \[{"role": "user", "content": "What happened in tech this week?"}\]}

41

)

42

print(response\["messages"\]\[\-1\].content)

* * *

## Search and Extract Pattern

Combine `YouSearchAPIWrapper` methods in a multi-step graph that searches the web, extracts full page content from the top results, and generates a comprehensive answer. The search step returns snippets and URLs (without `livecrawl`), then the extract step calls the Contents API to fetch full page content for the top results. This avoids fetching full content for every search result—only the most relevant URLs get crawled:

1

from langchain\_openai import ChatOpenAI

2

from langchain\_youdotcom import YouSearchAPIWrapper

3

from langgraph.graph import START, END, StateGraph, MessagesState

4

5

llm \= ChatOpenAI(model\="gpt-4o-mini")

6

wrapper \= YouSearchAPIWrapper(count\=5)

7

8

9

class SearchState(MessagesState):

10

    urls: list\[str\]

11

12

13

def search\_web(state: SearchState):

14

    """Search the web and extract URLs from the results."""

15

    query \= state\["messages"\]\[\-1\].content

16

    docs \= wrapper.results(query)

17

    urls \= \[doc.metadata\["url"\] for doc in docs if "url" in doc.metadata\]

18

    results\_text \= "\\n\\n".join(

19

        f"{doc.metadata.get('title', 'Untitled')}: {doc.page\_content\[:200\]}"

20

        for doc in docs

21

    )

22

    return {

23

        "messages": \[

24

            {"role": "system", "content": f"Search results:\\n\\n{results\_text}"}

25

        \],

26

        "urls": urls,

27

    }

28

29

30

def extract\_content(state: SearchState):

31

    """Extract full content from the URLs found in search."""

32

    urls \= state.get("urls", \[\])\[:3\]

33

    if not urls:

34

        return {"messages": \[\]}

35

    docs \= wrapper.contents(urls)

36

    content \= "\\n\\n".join(doc.page\_content for doc in docs)

37

    return {

38

        "messages": \[

39

            {"role": "system", "content": f"Extracted content:\\n\\n{content}"}

40

        \]

41

    }

42

43

44

def synthesize(state: SearchState):

45

    """Generate a final answer from all gathered context."""

46

    response \= llm.invoke(state\["messages"\])

47

    return {"messages": \[response\]}

48

49

50

graph \= StateGraph(SearchState)

51

graph.add\_node("search", search\_web)

52

graph.add\_node("extract", extract\_content)

53

graph.add\_node("synthesize", synthesize)

54

55

graph.add\_edge(START, "search")

56

graph.add\_edge("search", "extract")

57

graph.add\_edge("extract", "synthesize")

58

graph.add\_edge("synthesize", END)

59

60

app \= graph.compile()

61

62

response \= app.invoke(

63

    {"messages": \[{"role": "user", "content": "Explain the latest advances in quantum computing"}\]}

64

)

65

print(response\["messages"\]\[\-1\].content)

* * *

## Configuration Reference

Both tools accept a `YouSearchAPIWrapper` via the `api_wrapper` parameter. Here are the key options:

### Search Options

###### Result volume

`count` sets the max results per section. `offset` controls pagination in multiples of `count`. `k` limits max documents after the API response.

###### Filtering

`freshness`, `country`, `safesearch`, and `language` narrow results by age, location, moderation level, and BCP 47 language code.

###### Live page content

`livecrawl` fetches live page content from `web`, `news`, or `all` results. `livecrawl_formats` controls whether that content is returned as `html` or `markdown`.

###### Wrapper behavior

`n_snippets_per_hit` controls snippets per search result at the wrapper layer, after the API response.

### Contents Options

`YouContentsTool` accepts `urls: list[str]` at invocation. To control the output format or crawl timeout, call `api_wrapper.contents()` directly:

1

from langchain\_youdotcom import YouSearchAPIWrapper

2

3

wrapper \= YouSearchAPIWrapper()

4

docs \= wrapper.contents(

5

    \["https://example.com"\],

6

    formats\=\["markdown", "metadata"\],  # default

7

    crawl\_timeout\=30,                  # seconds (1–60)

8

)

For full parameter details, see the [Web Search API reference](https://you.com/docs/api-reference/search/v1-search) and [Contents API reference](https://you.com/docs/api-reference/contents).

* * *

## Resources