> ## Documentation Index
> Fetch the complete documentation index at: https://docs.doconda.com/llms.txt
> Use this file to discover all available pages before exploring further.

# How to return documents from a LangGraph agent

> Turn doconda.tools() into StructuredTool and add them to your graph: the agent creates Word, PowerPoint, Excel or PDF files and returns links.

Install `langgraph` and `doconda`, turn each tool from `doconda.tools()` into a `StructuredTool` (its JSON Schema works
as `args_schema`) and pass them to the agent or a `ToolNode`. The agent calls `create_document` and its last message
carries the links to the Word, PowerPoint, Excel or PDF file.

## Steps

1. Put your Doconda API key (dashboard → **API keys**) in `DOCONDA_API_KEY` and your model provider's key (here,
   `OPENAI_API_KEY`).
2. Install the dependencies: `pip install langgraph "langchain[openai]" doconda`.
3. Build the graph with the tools:

```python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
from doconda import Doconda
from langchain.chat_models import init_chat_model
from langchain_core.tools import StructuredTool
from langgraph.graph import START, MessagesState, StateGraph
from langgraph.prebuilt import ToolNode, tools_condition


def as_langchain_tool(t):
    return StructuredTool(name=t.name, description=t.description, args_schema=t.input_schema, func=lambda **args: t.run(args))


tools = [as_langchain_tool(t) for t in Doconda().tools()]
model = init_chat_model("openai:gpt-5").bind_tools(tools)


def call_model(state: MessagesState):
    return {"messages": [model.invoke(state["messages"])]}


graph = (
    StateGraph(MessagesState)
    .add_node("model", call_model)
    .add_node("tools", ToolNode(tools))
    .add_edge(START, "model")
    .add_conditional_edges("model", tools_condition)
    .add_edge("tools", "model")
    .compile()
)

result = graph.invoke({"messages": [{"role": "user", "content": "Write a quarterly sales report in Word"}]})
print(result["messages"][-1].content)
```

If you don't need your own graph, `create_agent("openai:gpt-5", tools)` from `langchain.agents` is LangGraph's prebuilt
ReAct agent and returns a compiled graph just the same: with `checkpointer`, streaming and interrupts.

## What you get back

The `tools` node adds a `ToolMessage` with the tool's summary to the state:

```json theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
{
  "id": "doc_01JAB3…",
  "format": "docx",
  "status": "ready",
  "links": { "docx": "https://…", "pdf": "https://…" },
  "links_note": "Links expire in 5 minutes: call get_document for fresh ones."
}
```

* Keep the `id` in the graph state if a later step has to edit the document (`edit_document`) or get fresh links
  (`get_document`): links expire after 5 minutes.
* `status`: `ready`, `ready_with_warnings`, `needs_review` or `failed` (not charged).

## FAQ

<AccordionGroup>
  <Accordion title="Can I use MCP instead of the Python SDK?">
    Yes: the tools come from `langchain-mcp-adapters` against `https://api.eu.doconda.com/mcp`, as in
    [LangChain](/en/agents/langchain).
  </Accordion>

  <Accordion title="Can I add a human approval before the document is sent?">
    Yes. It's a regular compiled graph: add an interrupt after the `tools` node and check the `status` and the report
    (`get_report`) before continuing.
  </Accordion>

  <Accordion title="Which formats does it create?">
    Word, PDF, PowerPoint, Excel and artifacts (a web page with its own data). Word, PowerPoint and Excel files come with
    their PDF.
  </Accordion>

  <Accordion title="How much does it cost?">
    You pay per delivered document. See [pricing](/en/guides/account#pricing).
  </Accordion>
</AccordionGroup>

## Keep reading

* [LangGraph](/en/agents/langgraph): the full guide.
* [Quickstart](/en/quickstart).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.