{"id":50984997,"url":"https://github.com/bayars/langchain-langgraph-deep-agent-patterns","last_synced_at":"2026-06-19T18:03:52.830Z","repository":{"id":352541253,"uuid":"1215547867","full_name":"bayars/langchain-langgraph-deep-agent-patterns","owner":"bayars","description":"A proof-of-concept comparing two approaches to serving LangGraph agents over HTTP: raw FastAPI SSE with a hand-rolled event schema, and the Aegra-style LangGraph Platform REST API. Features a simple UI with an in-memory data store, a Deep Agent with a virtual file system, planning, LLM SKILLS.md, and HITL interrupts all streaming live to a UI.","archived":false,"fork":false,"pushed_at":"2026-04-20T03:17:14.000Z","size":73,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-20T05:08:04.122Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bayars.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-20T02:55:47.000Z","updated_at":"2026-04-20T03:17:18.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/bayars/langchain-langgraph-deep-agent-patterns","commit_stats":null,"previous_names":["bayars/langchain-langgraph-deep-agent-patterns"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/bayars/langchain-langgraph-deep-agent-patterns","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bayars%2Flangchain-langgraph-deep-agent-patterns","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bayars%2Flangchain-langgraph-deep-agent-patterns/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bayars%2Flangchain-langgraph-deep-agent-patterns/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bayars%2Flangchain-langgraph-deep-agent-patterns/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bayars","download_url":"https://codeload.github.com/bayars/langchain-langgraph-deep-agent-patterns/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bayars%2Flangchain-langgraph-deep-agent-patterns/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34542467,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-19T02:00:06.005Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-19T18:03:52.280Z","updated_at":"2026-06-19T18:03:52.819Z","avatar_url":"https://github.com/bayars.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# langgraph-agent-patterns\n\nA proof-of-concept comparing two approaches to serving LangGraph agents over HTTP: **raw FastAPI SSE** with a hand-rolled event schema, and the **Aegra-style LangGraph Platform REST API**. Features a simple ReAct agent with an in-memory data store, and a Deep Agent with a virtual file system, todo-based planning, specialized LLM skills, and human-in-the-loop interrupts — all streaming live to a React UI backed by local Ollama models.\n\n---\n\n## What's inside\n\n| Component | Description |\n|-----------|-------------|\n| **Simple Agent** | `create_react_agent` + KV store tools. Demonstrates the minimal LangGraph pattern. |\n| **Deep Agent** | Custom `StateGraph` with VFS, todo planning, sub-LLM skills, and HITL interrupt. |\n| **Skills** | `analyze_data` (qwen3:8b), `write_code` (qwen2.5-coder:14b), `search_knowledge` — each skill runs its own LLM in isolation. |\n| **FastAPI server** | Port 8000. Raw SSE, custom `data.type` event schema. |\n| **Aegra server** | Port 8001. LangGraph Platform REST spec — typed `event:` SSE headers, `/threads`, `/runs/stream`. |\n| **React GUI** | CDN-only (no build step). Token streaming, tool spinners, VFS file browser, HITL modal. |\n| **Presentation** | Reveal.js deck — architecture, patterns, platform integration. |\n\n---\n\n## Prerequisites\n\n- Python 3.11+\n- [Ollama](https://ollama.com) running with the following models pulled:\n\n```bash\nollama pull qwen3:8b\nollama pull qwen2.5-coder:14b\nollama pull llama3.1:8b\n```\n\nSet `OLLAMA_BASE_URL` in `agents/config.py` if your Ollama is not at `http://10.0.0.224:11434`.\n\n---\n\n## Quick start\n\n```bash\ngit clone https://github.com/your-org/langgraph-agent-patterns\ncd langgraph-agent-patterns\nbash run.sh\n```\n\n`run.sh` installs dependencies and starts both servers.\n\n| URL | Description |\n|-----|-------------|\n| `http://localhost:8000` | React GUI (FastAPI mode) |\n| `http://localhost:8001` | React GUI (Aegra mode) |\n| `http://localhost:8000/presentation` | Reveal.js slide deck |\n| `http://localhost:8000/docs` | FastAPI Swagger UI |\n| `http://localhost:8001/docs` | Aegra Swagger UI |\n| `http://localhost:8000/test` | Minimal SSE diagnostic page |\n\n---\n\n## Project structure\n\n```\nagents/\n├── agents/\n│   ├── config.py          # Ollama URLs and model constants\n│   ├── simple_agent.py    # ReAct agent — write/read/list_data tools\n│   ├── skills.py          # analyze_data, write_code, search_knowledge\n│   └── deep_agent.py      # StateGraph: VFS + todos + skills + HITL\n├── servers/\n│   ├── fastapi_server.py  # Raw SSE, custom event schema (port 8000)\n│   └── aegra_server.py    # LangGraph Platform REST API (port 8001)\n├── frontend/\n│   ├── index.html         # React 18 GUI (CDN, no build)\n│   └── test.html          # Plain XHR SSE diagnostic\n├── presentation/\n│   └── index.html         # Reveal.js slides\n├── requirements.txt\n├── Dockerfile\n├── docker-compose.yml\n└── run.sh\n```\n\n---\n\n## Example prompts\n\n**Simple agent**\n```\nWrite name=Alice role=engineer to the data store, then read it back.\n```\n\n**Deep agent — planning + skills**\n```\nAnalyze this dataset: sales=120, users=80, churn=5%.\nSave findings to report.txt and write Python to plot the data.\n```\n\n**Deep agent — HITL**\n```\nSearch for sales trends, then ask me how detailed the report should be.\n```\n\n---\n\n## API reference\n\n### FastAPI (port 8000)\n\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| `POST` | `/api/simple/stream` | Stream simple agent — body: `{message, thread_id}` |\n| `POST` | `/api/deep/stream` | Stream deep agent — body: `{message, thread_id}` |\n| `POST` | `/api/resume/{thread_id}` | Resume HITL interrupt — body: `{choice}` |\n| `GET`  | `/api/threads/{id}/vfs` | VFS file snapshot |\n| `GET`  | `/api/threads/{id}/todos` | Todo list snapshot |\n| `GET`  | `/api/store` | Simple agent KV store |\n| `GET`  | `/api/test/stream` | Mock SSE stream (no Ollama needed) |\n\nSSE event format:\n```\ndata: {\"type\": \"token\",      \"content\": \"...\"}\ndata: {\"type\": \"tool_start\", \"tool\": \"write_file\", \"input\": {...}}\ndata: {\"type\": \"tool_end\",   \"tool\": \"write_file\", \"output\": \"...\"}\ndata: {\"type\": \"vfs_update\", \"files\": {...}}\ndata: {\"type\": \"interrupt\",  \"question\": \"...\", \"options\": [...]}\ndata: {\"type\": \"done\"}\n```\n\n### Aegra (port 8001)\n\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| `GET`  | `/assistants` | List available agents |\n| `POST` | `/threads` | Create a thread |\n| `GET`  | `/threads/{id}` | Thread metadata |\n| `GET`  | `/threads/{id}/state` | Full state snapshot |\n| `POST` | `/threads/{id}/runs/stream` | Stream a run — body: `{assistant_id, input}` |\n| `POST` | `/threads/{id}/runs/{rid}/resume` | Resume interrupt — body: `{values}` |\n| `GET`  | `/threads/{id}/runs` | List runs for thread |\n\nSSE event names: `metadata` · `updates` · `messages/partial` · `tool_start` · `tool_end` · `interrupt` · `values` · `end`\n\n---\n\n## Architecture notes\n\n### Why two servers?\n\nFastAPI raw SSE is the path most teams start on — it's quick to wire up but creates a tight client/server coupling around a custom event schema. Aegra implements the open [LangGraph Platform REST spec](https://langchain-ai.github.io/langgraph/concepts/langgraph_server/), so any client that speaks the SDK (JS, Python, LangFlow) works against it without modification.\n\nThe same LangGraph agent code runs behind both. The server layer is the only difference.\n\n### Deep Agent internals\n\nThe Deep Agent is a hand-authored `StateGraph` rather than `create_react_agent`. This gives explicit control over:\n\n- **VFS** — files written by the agent live in a per-thread dict, not in the context window. The LLM writes a path; humans or tools read it back.\n- **Todos** — the agent can call `write_todos` to publish its plan before executing it. Clients see the plan in real time.\n- **Skills bus** — `analyze_data`, `write_code`, and `search_knowledge` are LangGraph tools that each spin up their own `ChatOllama` instance. The orchestrator model chooses which skill to invoke; the skill model does the specialised work.\n- **HITL** — `request_options` calls `interrupt()`, which serializes the full graph state to `MemorySaver`. The agent is paused until `Command(resume=choice)` is sent.\n\n### Nesting LangGraph agents\n\nAny compiled LangGraph graph can be wrapped as a tool and given to a parent agent. This is how the Deep Agent pattern scales: a top-level orchestrator graph calls sub-graphs (the skills) as opaque tools, each with their own state and checkpointer if needed.\n\n```python\n@tool\ndef run_sub_agent(task: str, config: RunnableConfig) -\u003e str:\n    \"\"\"Delegate a task to the specialized sub-agent.\"\"\"\n    result = SUB_AGENT.invoke(\n        {\"messages\": [{\"role\": \"user\", \"content\": task}]},\n        config=config\n    )\n    return result[\"messages\"][-1].content\n```\n\n---\n\n## Docker\n\n```bash\ndocker compose up\n```\n\nBoth servers start on ports 8000 and 8001. Set `OLLAMA_BASE_URL` as an environment variable to point at your Ollama host.\n\n---\n\n## Stack\n\n| Layer | Library | License |\n|-------|---------|---------|\n| Agent framework | LangGraph | MIT |\n| LLM interface | LangChain + langchain-ollama | MIT |\n| HTTP server | FastAPI + uvicorn | MIT |\n| SSE | sse-starlette | BSD |\n| Platform API | Aegra pattern | Apache 2.0 |\n| Frontend | React 18 (CDN) | MIT |\n| Presentation | Reveal.js (CDN) | MIT |\n| Models | Ollama (local) | MIT |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbayars%2Flangchain-langgraph-deep-agent-patterns","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbayars%2Flangchain-langgraph-deep-agent-patterns","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbayars%2Flangchain-langgraph-deep-agent-patterns/lists"}