Observed since 20 Oct, 22:16 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Graph-native framework for building AI agents with FalkorDB persistence
Graph-native framework for building AI agents with persistent execution state.
Every agent's execution is a directed graph—GOAL → TASK → ACTION → SYNTHESIS. Persistence is backed by FalkorDB, so you can inspect the full state of every agent at http://localhost:3000.
pip install agentic-graphs
uvx agentic-graphs # or
uv add agentic-graphs
# Use other LLM providers
pip install agentic-graphs[anthropic,gemini,groq] # or [all]
# Development
pip install agentic-graphs[dev]
docker run -d -p 6379:6379 -p 3000:3000 --name falkordb falkordb/falkordb:latest
Then open http://localhost:3000 to inspect agent state.
import asyncio
from agentic_graphs import Agent, OpenAILLM, tool
@tool
def add(a: float, b: float) -> float:
"""Add two numbers."""
return a + b
@tool
def multiply(a: float, b: float) -> float:
"""Multiply two numbers."""
return a * b
class MathAgent(Agent):
"""Simple math agent with custom tools."""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._extra_action_tools = {"add": add, "multiply": multiply}
self._extra_action_schemas = [add.schema, multiply.schema]
def build_tools(self, node):
schemas, impls = super().build_tools(node)
schemas += self._extra_action_schemas
impls.update(self._extra_action_tools)
return schemas, impls
async def main():
llm = OpenAILLM(model="gpt-4o-mini")
agent = MathAgent(llm, "What is (17 * 3 + 42) / 9?")
result = await agent.run()
print(f"Answer: {result}")
asyncio.run(main())
from agentic_graphs.session import Session
from agentic_graphs.core.falkordb_backend import FalkorDBBackend
async def chat():
session = await Session.create(
llm=OpenAILLM(model="gpt-4o-mini"),
agent_class=MathAgent,
backend=FalkorDBBackend(),
thread_name="math-session",
user_id="alice",
)
# Each turn builds a fresh graph, history is auto-injected
reply = await session.chat("What is 5 * 8?")
print(reply)
reply = await session.chat("Add 10 to that result")
print(reply)
# Resume later by thread ID
session = await Session.create(..., thread_id=session.thread_id)
# Math agent (single-turn)
uv run python -m agentic_graphs.examples.math_agent "What is 15 + 27?"
uv run python -m agentic_graphs.examples.math_agent --chat # Interactive
# Multi-turn chat session
uv run python -m agentic_graphs.examples.chat_session
# Multi-agent with subagents (research + math)
uv run python -m agentic_graphs.examples.multi_agent_demo
# Session debugger — inspect execution graphs
uv run python -m agentic_graphs.examples.debug_session
uv run python -m agentic_graphs.examples.debug_session --thread <thread-id>
Open http://localhost:3000 to see the graph state in real-time.
Every agent execution builds a directed graph. Node types and states:
GOAL → TASK → ACTION → SYNTHESIS → (resolved)
↓
(pending/ready/active/resolved/failed)
Agents automatically have:
create_task(label, ...) — create a TASK nodecreate_action(label, instruction) — create an ACTION noderesolve_current_node(output) — mark node as RESOLVEDadd_dependency(waiting, prereq) — set up blocking edgesget_token_usage() — retrieve accumulated token costsACTION nodes also get your custom tools (e.g., add, multiply).
Subagents — delegate to child agents in sub-GOAL nodes:
agent.register_subagent(
"researcher",
agent_class=ResearchAgent,
description="Research any topic",
)
Skills — progressive disclosure of domain tools:
agent.register_skill(
"web_search",
tools=[search.schema],
tool_fns={"search": search},
description="Search the web",
)
Handoffs — state-driven agent switching:
if "financial" in task:
await agent.handoff_to("financial_analyst")
Switch providers with:
from agentic_graphs import AnthropicLLM, GeminiLLM
llm = AnthropicLLM(model="claude-sonnet-4")
llm = GeminiLLM(model="gemini-2.0-flash")
Each node tracks cumulative token costs:
agent = Agent(llm, goal)
result = await agent.run()
# Check usage on any node
for node_id, node in agent.graph.nodes.items():
usage = node.props.get("_usage", {})
print(f"{node.label}: {usage.get('total_tokens')} tokens")
Graph Model:
Graph objectScheduler:
Backend:
See docs/ARCHITECTURE.md for deep dive.
export OPENAI_API_KEY=sk-... # OpenAI
export ANTHROPIC_API_KEY=sk-ant-... # Anthropic
export GOOGLE_API_KEY=AIzaSy... # Gemini
export GROQ_API_KEY=gsk_... # Groq
export FALKORDB_HOST=localhost # FalkorDB (default: localhost:6379)
llm = OpenAILLM(model="gpt-4o-mini", timeout=300.0)
uv run pytest tests/ -v
uv run ruff check src/ # Linting
Pull requests welcome! Please:
uv run ruff check src/ --fix before committingMIT — see LICENSE
asyncio.gather, fan-in via REQUIRES edgesfrom agentic_graphs import FalkorDBBackend, Graph, Node, NT
backend = FalkorDBBackend(graph_name="my_agent")
# Push
backend.sync(my_graph)
# Pull
restored = backend.load("my_agent")
# Query
result = backend.query("MATCH (n:GOAL) RETURN n.label, n.state")
for row in result.result_set:
print(row)
# Auto-sync every mutation
from agentic_graphs import set_sync_hook
set_sync_hook(lambda g: backend.sync(g))
src/agentic_graphs/
├── __init__.py # Public API
├── log.py # Coloured logging
├── core/
│ ├── graph.py # Graph, Node, Edge, algorithms
│ ├── tool.py # @tool decorator
│ └── falkordb_backend.py # FalkorDB persistence
├── llm/
│ ├── base.py # Abstract LLM interface
│ └── openai.py # OpenAI provider
├── agent/
│ ├── base.py # Agent base class (history_messages support)
│ ├── defaults.py # Default prompts, guides, mutation tools
│ └── scheduler.py # Run loop with retry + concurrency
├── session/
│ ├── models.py # Thread, Turn, TurnStatus, SessionConfig
│ ├── store.py # ThreadStore — FalkorDB-backed persistence
│ └── session.py # Session — multi-turn chat with graph traceability
└── examples/
├── math_agent.py # Math solver with @tool tools
├── multi_agent.py # Coordinator + parallel sub-agents
├── research_agent.py # Single research agent (fixed)
├── chat_session.py # Multi-turn session demo (new)
└── debug_session.py # Session debugger (new)
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.2.2 | 15 May 2026 | 11 |
This describes our collected data; it is not a security assessment.
Observed since 20 Oct, 22:16 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:bad41e750202baf321017df2b48c40680d1349c5d374e55790165de0bca012e0