Skip to main content

Actions Graph

Store and track LLM actions, tool calls, and sessions in Memgraph.

Part of the Context Graph family — usually wired into agent-context-graph to capture Claude Code / Codex sessions automatically. This README covers using it directly.

Actions Graph provides a graph-based storage system for tracking all LLM interactions, including:

  • Tool Calls: Function/tool invocations by the LLM
  • Tool Results: Outputs from tool executions
  • Messages: User, assistant, and system messages
  • Structured Outputs: Validated JSON outputs from the LLM
  • Subagent Events: Subagent lifecycle tracking
  • Sessions: Conversation session management

Features

  • 📊 Graph-based Storage: Store actions as nodes with relationships in Memgraph
  • 🔗 Temporal Sequences: Track action order with FOLLOWED_BY relationships
  • 🌳 Nested Actions: Support for parent-child action relationships (e.g., subagents)
  • 🏷️ Session Management: Create, track, and query sessions
  • 📈 Analytics: Built-in queries for tool usage stats and session summaries
  • 🔌 Agent Context Graph Integration: Consume normalized runtime events through ActionsGraphConnector

Installation

pip install actions-graph

For Agent Context Graph integration:

pip install "actions-graph[agent-context-graph]"

Needs a running Memgraph (default bolt://localhost:7687); ActionsGraph() reads MEMGRAPH_URL, MEMGRAPH_USER, MEMGRAPH_PASSWORD, MEMGRAPH_DATABASE (or takes them as kwargs):

docker run --rm -p 7687:7687 memgraph/memgraph

Quick Start

Basic Usage

from actions_graph import ActionsGraph, Session

# Initialize the graph
graph = ActionsGraph()  # reads MEMGRAPH_URL / MEMGRAPH_USER / MEMGRAPH_PASSWORD
graph.setup()  # Create indexes and constraints

# Create a session
session = Session(
    session_id="session-123",
    model="claude-sonnet-4-20250514",
    working_directory="/path/to/project",
)
graph.create_session(session)

# Record a tool call
tool_call = graph.record_tool_call(
    session_id="session-123",
    tool_name="Read",
    tool_input={"file_path": "/path/to/file.py"},
    tool_use_id="tool-use-001",
)

# Record the result
tool_result = graph.record_tool_result(
    session_id="session-123",
    tool_use_id="tool-use-001",
    tool_name="Read",
    content="def hello():\n    print('Hello, World!')",
)

# Get session summary
summary = graph.get_session_summary("session-123")
print(f"Actions: {summary['action_count']}, Tools: {summary['tool_call_count']}")

Agent Context Graph Integration

from actions_graph import ActionsGraph
from actions_graph.connector import ActionsGraphConnector
from agent_context_graph import AgentLink
from agent_context_graph.adapters.claude import ClaudeAdapter

graph = ActionsGraph()
graph.setup()

link = AgentLink()
link.add_connector(ActionsGraphConnector(graph))

adapter = ClaudeAdapter(link, session_id="my-session-123")
hooks = adapter.get_runtime_hooks()

Actions Graph should consume runtime activity through Agent Context Graph when possible. Runtime adapters normalize SDK callbacks and command hooks into the shared Event Protocol; ActionsGraphConnector decides which events become session and action nodes.

Graph Schema

Nodes

  • Session: LLM conversation sessions

    • Properties: session_id, started_at, ended_at, status, model, total_cost_usd, etc.
  • Action: Individual actions with type-specific labels

    • Labels: ToolCall, ToolResult, Message (plus a role label UserMessage/AssistantMessage/SystemMessage), StructuredOutput, SubagentEvent, PermissionRequest, ErrorEvent, RateLimitEvent
    • Properties: action_id, action_type, timestamp, status, duration_ms, parent_action_id, tool_name, tool_use_id (tool calls and results: the harness's id for the call), is_error, is_mcp, text (user and assistant messages only: the plain message text), properties (type-specific), metadata
    • The session link is the HAS_ACTION edge, not a property — there is no session_id on (:Action).
  • Tool: Tool definitions

    • Properties: name, is_mcp, mcp_server

Relationships

(:Session)-[:HAS_ACTION]->(:Action)
(:Action)-[:FOLLOWED_BY]->(:Action)   # temporal sequence
(:Action)-[:PARENT_OF]->(:Action)     # nested, e.g. subagent
(:Session)-[:FORKED_FROM]->(:Session)
(:Action)-[:USED_TOOL]->(:Tool)       # ToolCall actions only

API Reference

ActionsGraph

Main class for interacting with the graph.

graph = ActionsGraph()

# Setup
graph.setup()  # Create indexes
graph.drop()  # Remove indexes
graph.clear()  # Clear all data

# Sessions
graph.create_session(session)
graph.get_session(session_id)
graph.end_session(session_id, status=ActionStatus.COMPLETED)
graph.list_sessions(limit=100, status=None)  # keyword-only args

# Actions
graph.record_action(action)
graph.record_tool_call(session_id, tool_name, tool_input, ...)
graph.record_tool_result(session_id, tool_use_id, tool_name, content, ...)
graph.record_message(session_id, role, content, ...)
graph.get_action(action_id)
graph.get_session_actions(session_id, action_type=None, limit=1000)

# Analytics
graph.get_tool_usage_stats(session_id=None)
graph.get_action_sequence(session_id, include_content=False)
graph.get_session_summary(session_id)

Action Types

Type Model Class Description
tool_call ToolCall Tool/function invocation
tool_result ToolResult Tool execution result
user_message Message User input
assistant_message Message LLM response
system_message Message System messages
structured_output StructuredOutput Validated JSON output
subagent_start SubagentEvent Subagent started
subagent_stop SubagentEvent Subagent completed
error ErrorEvent Error occurred
permission_request PermissionRequest Permission requested
rate_limit RateLimitEvent Rate limit event

Agent Context Graph Connector

from actions_graph.connector import ActionsGraphConnector

connector = ActionsGraphConnector(graph)
link.add_connector(connector)

The connector records:

  • SessionStartEvent and SessionEndEvent as session lifecycle data
  • ToolStartEvent as ToolCall action nodes
  • ToolEndEvent as ToolResult action nodes
  • MessageEvent, AgentStartEvent, AgentEndEvent, and ErrorOccurredEvent as action nodes

Claude Agent SDK Hooks

Direct Claude Agent SDK hooks remain available for standalone use, but Agent Context Graph is the preferred integration path when multiple graph components need the same runtime event stream.

For Claude Agent SDK integration:

from actions_graph.hooks import create_tracking_hooks, ActionTracker

# Simple usage
hooks = create_tracking_hooks(graph, session_id)

# Advanced usage with custom tracker
tracker = ActionTracker(
    graph,
    session_id,
    track_tool_calls=True,
    track_tool_results=True,
    track_messages=True,
    track_subagents=True,
    track_permissions=True,
    track_errors=True,
)

Example Queries

Find sessions with errors

sessions = graph.list_sessions(status=ActionStatus.FAILED)

Get all tool calls in a session

from actions_graph import ActionType

tool_calls = graph.get_session_actions(
    session_id,
    action_type=ActionType.TOOL_CALL,
)

Custom Cypher queries

rows = graph._db.query(
    """
    MATCH (s:Session {session_id: $session_id})-[:HAS_ACTION]->(a:ToolCall)
    RETURN a.tool_name AS tool, count(*) AS count
    ORDER BY count DESC
""",
    params={"session_id": "my-session"},
)

License

MIT

Metadata

Release files for actions-graph 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for actions-graph 0.4.0
File Size Uploaded
actions_graph-0.4.0.tar.gz 37.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for actions-graph 0.4.0
File Interpreter ABI Platform
actions_graph-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 64.3 kB

Release files / actions_graph-0.4.0.tar.gz

Download URL actions_graph-0.4.0.tar.gz
Size 37.8 kB
Tags Source
SHA-256 checksum
How to use checksums
49a6a744420b3279a24b06f9da924bf01cb2cef320188a76b6f23643253602fe
BLAKE2b-256 checksum
How to use checksums
4cf045875ab5a614a45164b47a742b1a4fca988c82235e91588f84c7829265d6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.24 {"installer":{"name":"uv","version":"0.12.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / actions_graph-0.4.0-py3-none-any.whl

Download URL actions_graph-0.4.0-py3-none-any.whl
Size 26.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0cd0dc0b56b9a376ca42fdb03c96eb2462fe17693b85b0cc515bf8e2015a1f23
BLAKE2b-256 checksum
How to use checksums
a4e20897907df5ca04aaf3dc1be2abb828da383acb10346b9c3ca802898cccff
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.24 {"installer":{"name":"uv","version":"0.12.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

0.4.1

2 release files

This release

0.4.0 This release

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page