activegraph 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- activegraph-1.0.0/PKG-INFO +282 -0
- activegraph-1.0.0/README.md +241 -0
- activegraph-1.0.0/activegraph/__init__.py +222 -0
- activegraph-1.0.0/activegraph/__main__.py +5 -0
- activegraph-1.0.0/activegraph/behaviors/__init__.py +1 -0
- activegraph-1.0.0/activegraph/behaviors/base.py +153 -0
- activegraph-1.0.0/activegraph/behaviors/decorators.py +218 -0
- activegraph-1.0.0/activegraph/cli/__init__.py +17 -0
- activegraph-1.0.0/activegraph/cli/main.py +793 -0
- activegraph-1.0.0/activegraph/cli/quickstart.py +556 -0
- activegraph-1.0.0/activegraph/core/__init__.py +1 -0
- activegraph-1.0.0/activegraph/core/clock.py +46 -0
- activegraph-1.0.0/activegraph/core/event.py +33 -0
- activegraph-1.0.0/activegraph/core/graph.py +846 -0
- activegraph-1.0.0/activegraph/core/ids.py +135 -0
- activegraph-1.0.0/activegraph/core/patch.py +47 -0
- activegraph-1.0.0/activegraph/core/view.py +59 -0
- activegraph-1.0.0/activegraph/errors.py +345 -0
- activegraph-1.0.0/activegraph/frame.py +15 -0
- activegraph-1.0.0/activegraph/llm/__init__.py +51 -0
- activegraph-1.0.0/activegraph/llm/anthropic.py +339 -0
- activegraph-1.0.0/activegraph/llm/cache.py +180 -0
- activegraph-1.0.0/activegraph/llm/errors.py +257 -0
- activegraph-1.0.0/activegraph/llm/prompt.py +420 -0
- activegraph-1.0.0/activegraph/llm/provider.py +66 -0
- activegraph-1.0.0/activegraph/llm/recorded.py +270 -0
- activegraph-1.0.0/activegraph/llm/types.py +130 -0
- activegraph-1.0.0/activegraph/observability/__init__.py +61 -0
- activegraph-1.0.0/activegraph/observability/logging.py +205 -0
- activegraph-1.0.0/activegraph/observability/metrics.py +219 -0
- activegraph-1.0.0/activegraph/observability/migration.py +404 -0
- activegraph-1.0.0/activegraph/observability/prometheus.py +101 -0
- activegraph-1.0.0/activegraph/observability/status.py +83 -0
- activegraph-1.0.0/activegraph/packs/__init__.py +999 -0
- activegraph-1.0.0/activegraph/packs/diligence/__init__.py +86 -0
- activegraph-1.0.0/activegraph/packs/diligence/behaviors.py +447 -0
- activegraph-1.0.0/activegraph/packs/diligence/fixtures/__init__.py +364 -0
- activegraph-1.0.0/activegraph/packs/diligence/fixtures/companies.py +511 -0
- activegraph-1.0.0/activegraph/packs/diligence/object_types.py +163 -0
- activegraph-1.0.0/activegraph/packs/diligence/prompts/document_researcher.md +25 -0
- activegraph-1.0.0/activegraph/packs/diligence/prompts/memo_synthesizer.md +35 -0
- activegraph-1.0.0/activegraph/packs/diligence/prompts/question_generator.md +25 -0
- activegraph-1.0.0/activegraph/packs/diligence/prompts/risk_identifier.md +26 -0
- activegraph-1.0.0/activegraph/packs/diligence/settings.py +60 -0
- activegraph-1.0.0/activegraph/packs/diligence/tools.py +124 -0
- activegraph-1.0.0/activegraph/packs/loader.py +709 -0
- activegraph-1.0.0/activegraph/packs/scaffold.py +317 -0
- activegraph-1.0.0/activegraph/policy.py +20 -0
- activegraph-1.0.0/activegraph/runtime/__init__.py +1 -0
- activegraph-1.0.0/activegraph/runtime/behavior_graph.py +151 -0
- activegraph-1.0.0/activegraph/runtime/budget.py +120 -0
- activegraph-1.0.0/activegraph/runtime/config_errors.py +124 -0
- activegraph-1.0.0/activegraph/runtime/diff.py +145 -0
- activegraph-1.0.0/activegraph/runtime/errors.py +216 -0
- activegraph-1.0.0/activegraph/runtime/exec_errors.py +232 -0
- activegraph-1.0.0/activegraph/runtime/patterns.py +946 -0
- activegraph-1.0.0/activegraph/runtime/queue.py +27 -0
- activegraph-1.0.0/activegraph/runtime/registration_errors.py +291 -0
- activegraph-1.0.0/activegraph/runtime/registry.py +111 -0
- activegraph-1.0.0/activegraph/runtime/runtime.py +2441 -0
- activegraph-1.0.0/activegraph/runtime/scheduler.py +206 -0
- activegraph-1.0.0/activegraph/runtime/view_builder.py +65 -0
- activegraph-1.0.0/activegraph/store/__init__.py +41 -0
- activegraph-1.0.0/activegraph/store/base.py +66 -0
- activegraph-1.0.0/activegraph/store/conformance.py +161 -0
- activegraph-1.0.0/activegraph/store/errors.py +84 -0
- activegraph-1.0.0/activegraph/store/memory.py +118 -0
- activegraph-1.0.0/activegraph/store/postgres.py +609 -0
- activegraph-1.0.0/activegraph/store/serde.py +202 -0
- activegraph-1.0.0/activegraph/store/sqlite.py +446 -0
- activegraph-1.0.0/activegraph/store/url.py +230 -0
- activegraph-1.0.0/activegraph/tools/__init__.py +64 -0
- activegraph-1.0.0/activegraph/tools/base.py +57 -0
- activegraph-1.0.0/activegraph/tools/cache.py +157 -0
- activegraph-1.0.0/activegraph/tools/context.py +48 -0
- activegraph-1.0.0/activegraph/tools/decorators.py +70 -0
- activegraph-1.0.0/activegraph/tools/errors.py +320 -0
- activegraph-1.0.0/activegraph/tools/graph_query.py +94 -0
- activegraph-1.0.0/activegraph/tools/recorded.py +205 -0
- activegraph-1.0.0/activegraph/tools/web_fetch.py +80 -0
- activegraph-1.0.0/activegraph/trace/__init__.py +1 -0
- activegraph-1.0.0/activegraph/trace/causal.py +123 -0
- activegraph-1.0.0/activegraph/trace/printer.py +495 -0
- activegraph-1.0.0/activegraph.egg-info/PKG-INFO +282 -0
- activegraph-1.0.0/activegraph.egg-info/SOURCES.txt +148 -0
- activegraph-1.0.0/activegraph.egg-info/dependency_links.txt +1 -0
- activegraph-1.0.0/activegraph.egg-info/entry_points.txt +5 -0
- activegraph-1.0.0/activegraph.egg-info/requires.txt +31 -0
- activegraph-1.0.0/activegraph.egg-info/top_level.txt +1 -0
- activegraph-1.0.0/pyproject.toml +190 -0
- activegraph-1.0.0/setup.cfg +4 -0
- activegraph-1.0.0/tests/test_activate_after.py +131 -0
- activegraph-1.0.0/tests/test_causal_cross_tool.py +139 -0
- activegraph-1.0.0/tests/test_cli.py +535 -0
- activegraph-1.0.0/tests/test_clock.py +15 -0
- activegraph-1.0.0/tests/test_diff.py +121 -0
- activegraph-1.0.0/tests/test_diligence_pack.py +196 -0
- activegraph-1.0.0/tests/test_diligence_with_tools.py +74 -0
- activegraph-1.0.0/tests/test_doc_links.py +299 -0
- activegraph-1.0.0/tests/test_doc_site_reachable.py +121 -0
- activegraph-1.0.0/tests/test_errors_format.py +1498 -0
- activegraph-1.0.0/tests/test_event.py +29 -0
- activegraph-1.0.0/tests/test_fork.py +167 -0
- activegraph-1.0.0/tests/test_graph.py +110 -0
- activegraph-1.0.0/tests/test_ids.py +22 -0
- activegraph-1.0.0/tests/test_llm_anthropic.py +185 -0
- activegraph-1.0.0/tests/test_llm_behavior.py +231 -0
- activegraph-1.0.0/tests/test_llm_budget.py +152 -0
- activegraph-1.0.0/tests/test_llm_causal.py +66 -0
- activegraph-1.0.0/tests/test_llm_claim_extraction.py +84 -0
- activegraph-1.0.0/tests/test_llm_determinism.py +106 -0
- activegraph-1.0.0/tests/test_llm_failure.py +214 -0
- activegraph-1.0.0/tests/test_llm_prompt.py +357 -0
- activegraph-1.0.0/tests/test_llm_provider_fixtures.py +132 -0
- activegraph-1.0.0/tests/test_llm_replay.py +263 -0
- activegraph-1.0.0/tests/test_llm_tool_loop.py +312 -0
- activegraph-1.0.0/tests/test_llm_trace.py +144 -0
- activegraph-1.0.0/tests/test_llm_trace_snapshot.py +112 -0
- activegraph-1.0.0/tests/test_llm_types.py +51 -0
- activegraph-1.0.0/tests/test_migration.py +190 -0
- activegraph-1.0.0/tests/test_observability_logging.py +135 -0
- activegraph-1.0.0/tests/test_observability_metrics.py +215 -0
- activegraph-1.0.0/tests/test_operate_example.py +40 -0
- activegraph-1.0.0/tests/test_pack_scaffold.py +119 -0
- activegraph-1.0.0/tests/test_packs.py +561 -0
- activegraph-1.0.0/tests/test_patch.py +61 -0
- activegraph-1.0.0/tests/test_pattern_matcher.py +160 -0
- activegraph-1.0.0/tests/test_pattern_parser.py +221 -0
- activegraph-1.0.0/tests/test_pattern_subscriptions.py +132 -0
- activegraph-1.0.0/tests/test_persistence.py +382 -0
- activegraph-1.0.0/tests/test_postgres_store.py +51 -0
- activegraph-1.0.0/tests/test_quickstart.py +309 -0
- activegraph-1.0.0/tests/test_quickstart_snapshot.py +72 -0
- activegraph-1.0.0/tests/test_replay.py +128 -0
- activegraph-1.0.0/tests/test_replay_trace_snapshot.py +51 -0
- activegraph-1.0.0/tests/test_requeue_unfired.py +206 -0
- activegraph-1.0.0/tests/test_resume_example.py +148 -0
- activegraph-1.0.0/tests/test_runtime.py +125 -0
- activegraph-1.0.0/tests/test_runtime_status.py +149 -0
- activegraph-1.0.0/tests/test_serde.py +65 -0
- activegraph-1.0.0/tests/test_store_conformance.py +46 -0
- activegraph-1.0.0/tests/test_store_url.py +57 -0
- activegraph-1.0.0/tests/test_tool_replay.py +196 -0
- activegraph-1.0.0/tests/test_tool_trace_snapshot.py +128 -0
- activegraph-1.0.0/tests/test_tools.py +282 -0
- activegraph-1.0.0/tests/test_trace.py +39 -0
- activegraph-1.0.0/tests/test_tutorial_snippets.py +167 -0
- activegraph-1.0.0/tests/test_version_sync.py +30 -0
- activegraph-1.0.0/tests/test_view.py +47 -0
- activegraph-1.0.0/tests/test_wheel_completeness.py +99 -0
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: activegraph
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: An event-sourced reactive graph runtime for long-running, auditable, agentic systems.
|
|
5
|
+
Author: Active Graph contributors
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/yoheinakajima/activegraph
|
|
8
|
+
Keywords: graph,agents,event-sourcing,runtime
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
|
15
|
+
Requires-Python: >=3.11
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
Requires-Dist: click<9,>=8
|
|
18
|
+
Requires-Dist: pydantic>=2
|
|
19
|
+
Provides-Extra: llm
|
|
20
|
+
Requires-Dist: anthropic>=0.40; extra == "llm"
|
|
21
|
+
Requires-Dist: pydantic>=2; extra == "llm"
|
|
22
|
+
Provides-Extra: sqlite
|
|
23
|
+
Provides-Extra: postgres
|
|
24
|
+
Requires-Dist: psycopg[binary]<4,>=3.1; extra == "postgres"
|
|
25
|
+
Provides-Extra: prometheus
|
|
26
|
+
Requires-Dist: prometheus_client>=0.20; extra == "prometheus"
|
|
27
|
+
Provides-Extra: all
|
|
28
|
+
Requires-Dist: anthropic>=0.40; extra == "all"
|
|
29
|
+
Requires-Dist: pydantic>=2; extra == "all"
|
|
30
|
+
Requires-Dist: psycopg[binary]<4,>=3.1; extra == "all"
|
|
31
|
+
Requires-Dist: prometheus_client>=0.20; extra == "all"
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
34
|
+
Requires-Dist: pydantic>=2; extra == "dev"
|
|
35
|
+
Requires-Dist: prometheus_client>=0.20; extra == "dev"
|
|
36
|
+
Requires-Dist: psycopg[binary]<4,>=3.1; extra == "dev"
|
|
37
|
+
Provides-Extra: docs
|
|
38
|
+
Requires-Dist: mkdocs>=1.6; extra == "docs"
|
|
39
|
+
Requires-Dist: mkdocs-material>=9.5; extra == "docs"
|
|
40
|
+
Requires-Dist: mkdocstrings[python]>=0.24; extra == "docs"
|
|
41
|
+
|
|
42
|
+
# Active Graph
|
|
43
|
+
|
|
44
|
+
> The graph is the world. Behaviors are physics. The trace is the proof.
|
|
45
|
+
|
|
46
|
+
An event-sourced reactive graph runtime for long-running, auditable,
|
|
47
|
+
agentic systems. Behaviors react to a shared graph instead of talking
|
|
48
|
+
to each other. Every change is traceable. Every run is resumable,
|
|
49
|
+
forkable, and diff-able from its event log.
|
|
50
|
+
|
|
51
|
+
If chat-based agents are a group conversation, Active Graph is a
|
|
52
|
+
shared workspace where everyone can see what changed, who changed
|
|
53
|
+
it, and why.
|
|
54
|
+
|
|
55
|
+
## Try it in 30 seconds
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pip install activegraph
|
|
59
|
+
activegraph quickstart
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The bundled Diligence pack runs against recorded fixtures: no API
|
|
63
|
+
key, no configuration, byte-deterministic output. You see what the
|
|
64
|
+
framework does before you read about how it does it.
|
|
65
|
+
|
|
66
|
+
Then walk the 10-minute tutorial:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
activegraph quickstart --interactive
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
It scaffolds a behavior, runs it against the same fixtures, and ends
|
|
73
|
+
with the fork-and-diff workflow — the framework's most differentiated
|
|
74
|
+
capability.
|
|
75
|
+
|
|
76
|
+
## Install
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
pip install activegraph # core runtime + SQLite store + Diligence pack
|
|
80
|
+
pip install "activegraph[llm]" # Anthropic provider
|
|
81
|
+
pip install "activegraph[postgres]" # Postgres-backed event store
|
|
82
|
+
pip install "activegraph[prometheus]" # Prometheus metrics
|
|
83
|
+
pip install "activegraph[all]" # everything
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Python 3.11+. Two hard dependencies (`click` for the CLI, `pydantic`
|
|
87
|
+
for the pack format); persistence backends and provider integrations
|
|
88
|
+
are opt-in extras.
|
|
89
|
+
|
|
90
|
+
## What you get
|
|
91
|
+
|
|
92
|
+
- **Event-sourced graph runtime.** Objects + typed relations + an
|
|
93
|
+
append-only event log. Every mutation is an event; the trace is the
|
|
94
|
+
audit trail.
|
|
95
|
+
- **Reactive behaviors as first-class.** Function, class, LLM-backed,
|
|
96
|
+
or attached to typed edges (the relation-behavior primitive — edges
|
|
97
|
+
with logic). Subscriptions are event type + predicate + a Cypher
|
|
98
|
+
subset for graph-shape patterns.
|
|
99
|
+
- **Fork-and-diff.** Branch any run at any event into an independent
|
|
100
|
+
fork, configure it differently, and structurally diff the result
|
|
101
|
+
against the parent. Cache replay means the shared prefix doesn't
|
|
102
|
+
re-execute (no new LLM calls). Most agent frameworks can't do this.
|
|
103
|
+
- **Packs.** A pack bundles object types, behaviors, tools, prompts,
|
|
104
|
+
and policies for a specific domain. The bundled
|
|
105
|
+
[Diligence pack](activegraph/packs/diligence) is the reference:
|
|
106
|
+
8 object types, 7 behaviors, 3 tools, recorded fixtures.
|
|
107
|
+
- **Per-error reference pages.** Every error message ends with a
|
|
108
|
+
`More:` link to a page that explains when it fires, why, and how to
|
|
109
|
+
fix it. Catalog at [docs.activegraph.ai/reference/errors](https://docs.activegraph.ai/reference/errors/).
|
|
110
|
+
|
|
111
|
+
## Concepts at a glance
|
|
112
|
+
|
|
113
|
+
The framework's twelve primitives, in roughly the order you meet them
|
|
114
|
+
when reading a trace. Each links to its concept page on the doc site;
|
|
115
|
+
read those when you want depth on one piece.
|
|
116
|
+
|
|
117
|
+
- **Graph** — objects and typed relations forming the world the
|
|
118
|
+
framework reasons about. The graph is a projection of the event log;
|
|
119
|
+
every mutation is an event. [→ concepts/graph](https://docs.activegraph.ai/concepts/graph/)
|
|
120
|
+
- **Events** — the append-only history. Every behavior fires in
|
|
121
|
+
response to events and produces more events; the trace is the
|
|
122
|
+
ordered log of all of them. [→ concepts/events](https://docs.activegraph.ai/concepts/events/)
|
|
123
|
+
- **Behaviors** — the unit of reactive code. Function, class, or
|
|
124
|
+
LLM-backed; declares what events it subscribes to and what it
|
|
125
|
+
produces. The determinism contract is per-behavior. [→ concepts/behaviors](https://docs.activegraph.ai/concepts/behaviors/)
|
|
126
|
+
- **Relations** — typed edges between objects, with their own
|
|
127
|
+
behaviors. The relation-behavior primitive — coordination logic on
|
|
128
|
+
the edge, not on either endpoint — is uncommon in other agent
|
|
129
|
+
frameworks. [→ concepts/relations](https://docs.activegraph.ai/concepts/relations/)
|
|
130
|
+
- **Patches** — proposed mutations with optimistic concurrency.
|
|
131
|
+
Behaviors propose patches; the runtime applies or rejects them;
|
|
132
|
+
rejections are events in their own right. [→ concepts/patches](https://docs.activegraph.ai/concepts/patches/)
|
|
133
|
+
- **Views** — scoped reads of the graph for behavior context. Type
|
|
134
|
+
filters, depth filters, recent-event windows. Views are how
|
|
135
|
+
pattern-driven behaviors see only what they need to. [→ concepts/views](https://docs.activegraph.ai/concepts/views/)
|
|
136
|
+
- **Frames** — bounded contexts for a run. Goal, constraints, budget,
|
|
137
|
+
and the registered behaviors for this frame. A run can have one
|
|
138
|
+
frame or many. [→ concepts/frames](https://docs.activegraph.ai/concepts/frames/)
|
|
139
|
+
- **Policies** — approval and gating for behavior capabilities. Which
|
|
140
|
+
behaviors can call which tools, which mutations require human
|
|
141
|
+
approval, what the runtime refuses. [→ concepts/policies](https://docs.activegraph.ai/concepts/policies/)
|
|
142
|
+
- **Patterns** — the Cypher subset for pattern subscriptions. Beyond
|
|
143
|
+
event-type + predicate, behaviors can subscribe to graph shapes
|
|
144
|
+
(claim-cited-by-evidence, task-blocks-task, …) with `NOT EXISTS`
|
|
145
|
+
and temporal predicates. [→ concepts/patterns](https://docs.activegraph.ai/concepts/patterns/)
|
|
146
|
+
- **Replay** — re-execute a run from its event log. Strict mode
|
|
147
|
+
re-fires every behavior and fails on divergence; permissive mode
|
|
148
|
+
reconstructs state without re-firing. The LLM replay cache is what
|
|
149
|
+
makes fork cheap. [→ concepts/replay](https://docs.activegraph.ai/concepts/replay/)
|
|
150
|
+
- **Forking** — branch any run at any event into an independent
|
|
151
|
+
fork; structurally diff the fork against the parent. The framework's
|
|
152
|
+
mechanism for hypothesis testing on agentic systems. [→ concepts/forking](https://docs.activegraph.ai/concepts/forking/)
|
|
153
|
+
- **Failure model** — a behavior failure is a `behavior.failed`
|
|
154
|
+
event, not an exception. The audit trail captures failures as
|
|
155
|
+
first-class history. Exceptions live at runtime entry points only.
|
|
156
|
+
[→ concepts/failure-model](https://docs.activegraph.ai/concepts/failure-model/)
|
|
157
|
+
|
|
158
|
+
## A small example
|
|
159
|
+
|
|
160
|
+
The relation-behavior primitive — coordination logic on the edge,
|
|
161
|
+
not on either endpoint:
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
from activegraph import Graph, Runtime, behavior, relation_behavior
|
|
165
|
+
|
|
166
|
+
graph = Graph()
|
|
167
|
+
runtime = Runtime(graph, budget={"max_events": 200, "max_seconds": 60})
|
|
168
|
+
|
|
169
|
+
@behavior(name="planner", on=["goal.created"])
|
|
170
|
+
def planner(event, graph, ctx):
|
|
171
|
+
research = graph.add_object("task", {"title": "Research", "status": "open"})
|
|
172
|
+
memo = graph.add_object("task", {"title": "Draft memo", "status": "blocked"})
|
|
173
|
+
graph.add_relation(research.id, memo.id, "depends_on")
|
|
174
|
+
|
|
175
|
+
@behavior(name="researcher", on=["object.created"], where={"object.type": "task"})
|
|
176
|
+
def researcher(event, graph, ctx):
|
|
177
|
+
task = event.payload["object"]
|
|
178
|
+
if task["data"]["status"] != "open" or "Research" not in task["data"]["title"]:
|
|
179
|
+
return
|
|
180
|
+
graph.add_object("claim", {"text": "Market early but growing.", "confidence": 0.7})
|
|
181
|
+
graph.emit("task.completed", {"task_id": task["id"]})
|
|
182
|
+
|
|
183
|
+
@relation_behavior(name="unblock", relation_type="depends_on", on=["task.completed"])
|
|
184
|
+
def unblock(relation, event, graph, ctx):
|
|
185
|
+
if event.payload["task_id"] == relation.source:
|
|
186
|
+
graph.patch_object(relation.target, {"status": "open"})
|
|
187
|
+
|
|
188
|
+
runtime.run_goal("Evaluate this startup idea")
|
|
189
|
+
runtime.print_trace()
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
The `unblock` relation behavior fires only for events touching one of
|
|
193
|
+
its edge endpoints. The conceptual deep-dive on edges-with-logic is
|
|
194
|
+
in [`docs/concepts/relations.md`](https://docs.activegraph.ai/concepts/relations/).
|
|
195
|
+
|
|
196
|
+
## Documentation
|
|
197
|
+
|
|
198
|
+
- **[docs.activegraph.ai](https://docs.activegraph.ai/)** — full doc site:
|
|
199
|
+
concepts, guides, cookbook, CLI reference, API reference, the
|
|
200
|
+
per-error catalog.
|
|
201
|
+
- **[10-minute tutorial](https://docs.activegraph.ai/quickstart/)** — install
|
|
202
|
+
to a working custom behavior, including fork-and-diff.
|
|
203
|
+
- **[CHANGELOG.md](CHANGELOG.md)** — every release, with per-version
|
|
204
|
+
migration notes.
|
|
205
|
+
- **[CONTRACT.md](CONTRACT.md)** — locked design decisions, version
|
|
206
|
+
by version. Useful when you want to know *why* something is the way
|
|
207
|
+
it is.
|
|
208
|
+
- **[examples/](examples)** — runnable end-to-end demos:
|
|
209
|
+
[`diligence_real_run.py`](examples/diligence_real_run.py),
|
|
210
|
+
[`resume_and_fork.py`](examples/resume_and_fork.py),
|
|
211
|
+
[`llm_claim_extraction.py`](examples/llm_claim_extraction.py),
|
|
212
|
+
[`diligence_with_tools.py`](examples/diligence_with_tools.py),
|
|
213
|
+
[`operate_a_run.py`](examples/operate_a_run.py).
|
|
214
|
+
|
|
215
|
+
## What this is not
|
|
216
|
+
|
|
217
|
+
- Not a chat framework. If your problem fits in one conversation, use
|
|
218
|
+
a chat framework.
|
|
219
|
+
- Not a workflow engine. Workflows model control flow. This models
|
|
220
|
+
world state.
|
|
221
|
+
- Not a rules engine, exactly. Rules engines forward-chain over
|
|
222
|
+
facts. This event-sources over a graph and supports LLM behaviors
|
|
223
|
+
as first-class.
|
|
224
|
+
- Not a production graph database. The default store is SQLite,
|
|
225
|
+
optionally Postgres. For a high-throughput graph backend, plug one
|
|
226
|
+
in behind the `EventStore` protocol.
|
|
227
|
+
- Not magic. Bad behaviors produce bad graphs. The runtime makes the
|
|
228
|
+
badness inspectable, not absent.
|
|
229
|
+
|
|
230
|
+
## Status
|
|
231
|
+
|
|
232
|
+
**v1.0 (stable)** (2026-05). The first-time-user gate per
|
|
233
|
+
[CONTRACT v1.0 #C4](CONTRACT.md#v10-c4-v10-ships-as-v10-rc1-first-time-user-gate-is-owned-externally)
|
|
234
|
+
ran through three rcs; v1.0 final ships rc3 plus a tutorial-step-7
|
|
235
|
+
output fix and a README "Concepts at a glance" index. See
|
|
236
|
+
[CHANGELOG.md](CHANGELOG.md) for the full v0 → v1.0 history and
|
|
237
|
+
per-version migration notes.
|
|
238
|
+
|
|
239
|
+
Major shipped milestones:
|
|
240
|
+
|
|
241
|
+
- **v1.0** — error hierarchy rewrite with per-error reference
|
|
242
|
+
pages, doc site at [docs.activegraph.ai](https://docs.activegraph.ai/),
|
|
243
|
+
`activegraph quickstart` command, mypy `--strict` and docstring
|
|
244
|
+
coverage CI gates, wheel-completeness and deploy-verification CI
|
|
245
|
+
gates.
|
|
246
|
+
- **v0.9** — pack format and the Diligence reference pack (8 object
|
|
247
|
+
types, 7 behaviors, 3 tools, recorded fixtures).
|
|
248
|
+
- **v0.8** — operator surface: structured logging, Prometheus
|
|
249
|
+
metrics, `runtime.status()`, full `activegraph` CLI,
|
|
250
|
+
`PostgresEventStore`.
|
|
251
|
+
- **v0.7** — `@tool` decorator, Cypher-subset pattern subscriptions,
|
|
252
|
+
temporal predicates.
|
|
253
|
+
- **v0.6** — `@llm_behavior` with structured output, frame-aware
|
|
254
|
+
prompt construction, cost accounting.
|
|
255
|
+
- **v0.5** — full event-log persistence, save/load across processes,
|
|
256
|
+
fork from any historical event, structural diff between runs.
|
|
257
|
+
- **v0** — core runtime: graph, behaviors, relation behaviors,
|
|
258
|
+
patches with optimistic concurrency, views, frames, policies,
|
|
259
|
+
budgets, the trace.
|
|
260
|
+
|
|
261
|
+
Roadmap items planned for v1.1 are tracked in
|
|
262
|
+
[CONTRACT.md § v1.1](CONTRACT.md).
|
|
263
|
+
|
|
264
|
+
## License
|
|
265
|
+
|
|
266
|
+
MIT.
|
|
267
|
+
|
|
268
|
+
## Contributing
|
|
269
|
+
|
|
270
|
+
The core runtime stays small and sharp. Contributions to packs,
|
|
271
|
+
backends, and LLM integrations are especially welcome. Open an issue
|
|
272
|
+
before large changes — the abstractions are still settling.
|
|
273
|
+
|
|
274
|
+
**Test discipline:** tests must remain deterministic. No live network
|
|
275
|
+
calls in CI. LLM and tool tests use recorded fixtures
|
|
276
|
+
(`RecordedLLMProvider`, `RecordedToolProvider`). If a contribution
|
|
277
|
+
adds a test that would only pass with a live API key or live HTTP,
|
|
278
|
+
it cannot land.
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
The graph is the world. Behaviors are physics. The trace is the proof.
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
# Active Graph
|
|
2
|
+
|
|
3
|
+
> The graph is the world. Behaviors are physics. The trace is the proof.
|
|
4
|
+
|
|
5
|
+
An event-sourced reactive graph runtime for long-running, auditable,
|
|
6
|
+
agentic systems. Behaviors react to a shared graph instead of talking
|
|
7
|
+
to each other. Every change is traceable. Every run is resumable,
|
|
8
|
+
forkable, and diff-able from its event log.
|
|
9
|
+
|
|
10
|
+
If chat-based agents are a group conversation, Active Graph is a
|
|
11
|
+
shared workspace where everyone can see what changed, who changed
|
|
12
|
+
it, and why.
|
|
13
|
+
|
|
14
|
+
## Try it in 30 seconds
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install activegraph
|
|
18
|
+
activegraph quickstart
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The bundled Diligence pack runs against recorded fixtures: no API
|
|
22
|
+
key, no configuration, byte-deterministic output. You see what the
|
|
23
|
+
framework does before you read about how it does it.
|
|
24
|
+
|
|
25
|
+
Then walk the 10-minute tutorial:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
activegraph quickstart --interactive
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
It scaffolds a behavior, runs it against the same fixtures, and ends
|
|
32
|
+
with the fork-and-diff workflow — the framework's most differentiated
|
|
33
|
+
capability.
|
|
34
|
+
|
|
35
|
+
## Install
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pip install activegraph # core runtime + SQLite store + Diligence pack
|
|
39
|
+
pip install "activegraph[llm]" # Anthropic provider
|
|
40
|
+
pip install "activegraph[postgres]" # Postgres-backed event store
|
|
41
|
+
pip install "activegraph[prometheus]" # Prometheus metrics
|
|
42
|
+
pip install "activegraph[all]" # everything
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Python 3.11+. Two hard dependencies (`click` for the CLI, `pydantic`
|
|
46
|
+
for the pack format); persistence backends and provider integrations
|
|
47
|
+
are opt-in extras.
|
|
48
|
+
|
|
49
|
+
## What you get
|
|
50
|
+
|
|
51
|
+
- **Event-sourced graph runtime.** Objects + typed relations + an
|
|
52
|
+
append-only event log. Every mutation is an event; the trace is the
|
|
53
|
+
audit trail.
|
|
54
|
+
- **Reactive behaviors as first-class.** Function, class, LLM-backed,
|
|
55
|
+
or attached to typed edges (the relation-behavior primitive — edges
|
|
56
|
+
with logic). Subscriptions are event type + predicate + a Cypher
|
|
57
|
+
subset for graph-shape patterns.
|
|
58
|
+
- **Fork-and-diff.** Branch any run at any event into an independent
|
|
59
|
+
fork, configure it differently, and structurally diff the result
|
|
60
|
+
against the parent. Cache replay means the shared prefix doesn't
|
|
61
|
+
re-execute (no new LLM calls). Most agent frameworks can't do this.
|
|
62
|
+
- **Packs.** A pack bundles object types, behaviors, tools, prompts,
|
|
63
|
+
and policies for a specific domain. The bundled
|
|
64
|
+
[Diligence pack](activegraph/packs/diligence) is the reference:
|
|
65
|
+
8 object types, 7 behaviors, 3 tools, recorded fixtures.
|
|
66
|
+
- **Per-error reference pages.** Every error message ends with a
|
|
67
|
+
`More:` link to a page that explains when it fires, why, and how to
|
|
68
|
+
fix it. Catalog at [docs.activegraph.ai/reference/errors](https://docs.activegraph.ai/reference/errors/).
|
|
69
|
+
|
|
70
|
+
## Concepts at a glance
|
|
71
|
+
|
|
72
|
+
The framework's twelve primitives, in roughly the order you meet them
|
|
73
|
+
when reading a trace. Each links to its concept page on the doc site;
|
|
74
|
+
read those when you want depth on one piece.
|
|
75
|
+
|
|
76
|
+
- **Graph** — objects and typed relations forming the world the
|
|
77
|
+
framework reasons about. The graph is a projection of the event log;
|
|
78
|
+
every mutation is an event. [→ concepts/graph](https://docs.activegraph.ai/concepts/graph/)
|
|
79
|
+
- **Events** — the append-only history. Every behavior fires in
|
|
80
|
+
response to events and produces more events; the trace is the
|
|
81
|
+
ordered log of all of them. [→ concepts/events](https://docs.activegraph.ai/concepts/events/)
|
|
82
|
+
- **Behaviors** — the unit of reactive code. Function, class, or
|
|
83
|
+
LLM-backed; declares what events it subscribes to and what it
|
|
84
|
+
produces. The determinism contract is per-behavior. [→ concepts/behaviors](https://docs.activegraph.ai/concepts/behaviors/)
|
|
85
|
+
- **Relations** — typed edges between objects, with their own
|
|
86
|
+
behaviors. The relation-behavior primitive — coordination logic on
|
|
87
|
+
the edge, not on either endpoint — is uncommon in other agent
|
|
88
|
+
frameworks. [→ concepts/relations](https://docs.activegraph.ai/concepts/relations/)
|
|
89
|
+
- **Patches** — proposed mutations with optimistic concurrency.
|
|
90
|
+
Behaviors propose patches; the runtime applies or rejects them;
|
|
91
|
+
rejections are events in their own right. [→ concepts/patches](https://docs.activegraph.ai/concepts/patches/)
|
|
92
|
+
- **Views** — scoped reads of the graph for behavior context. Type
|
|
93
|
+
filters, depth filters, recent-event windows. Views are how
|
|
94
|
+
pattern-driven behaviors see only what they need to. [→ concepts/views](https://docs.activegraph.ai/concepts/views/)
|
|
95
|
+
- **Frames** — bounded contexts for a run. Goal, constraints, budget,
|
|
96
|
+
and the registered behaviors for this frame. A run can have one
|
|
97
|
+
frame or many. [→ concepts/frames](https://docs.activegraph.ai/concepts/frames/)
|
|
98
|
+
- **Policies** — approval and gating for behavior capabilities. Which
|
|
99
|
+
behaviors can call which tools, which mutations require human
|
|
100
|
+
approval, what the runtime refuses. [→ concepts/policies](https://docs.activegraph.ai/concepts/policies/)
|
|
101
|
+
- **Patterns** — the Cypher subset for pattern subscriptions. Beyond
|
|
102
|
+
event-type + predicate, behaviors can subscribe to graph shapes
|
|
103
|
+
(claim-cited-by-evidence, task-blocks-task, …) with `NOT EXISTS`
|
|
104
|
+
and temporal predicates. [→ concepts/patterns](https://docs.activegraph.ai/concepts/patterns/)
|
|
105
|
+
- **Replay** — re-execute a run from its event log. Strict mode
|
|
106
|
+
re-fires every behavior and fails on divergence; permissive mode
|
|
107
|
+
reconstructs state without re-firing. The LLM replay cache is what
|
|
108
|
+
makes fork cheap. [→ concepts/replay](https://docs.activegraph.ai/concepts/replay/)
|
|
109
|
+
- **Forking** — branch any run at any event into an independent
|
|
110
|
+
fork; structurally diff the fork against the parent. The framework's
|
|
111
|
+
mechanism for hypothesis testing on agentic systems. [→ concepts/forking](https://docs.activegraph.ai/concepts/forking/)
|
|
112
|
+
- **Failure model** — a behavior failure is a `behavior.failed`
|
|
113
|
+
event, not an exception. The audit trail captures failures as
|
|
114
|
+
first-class history. Exceptions live at runtime entry points only.
|
|
115
|
+
[→ concepts/failure-model](https://docs.activegraph.ai/concepts/failure-model/)
|
|
116
|
+
|
|
117
|
+
## A small example
|
|
118
|
+
|
|
119
|
+
The relation-behavior primitive — coordination logic on the edge,
|
|
120
|
+
not on either endpoint:
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
from activegraph import Graph, Runtime, behavior, relation_behavior
|
|
124
|
+
|
|
125
|
+
graph = Graph()
|
|
126
|
+
runtime = Runtime(graph, budget={"max_events": 200, "max_seconds": 60})
|
|
127
|
+
|
|
128
|
+
@behavior(name="planner", on=["goal.created"])
|
|
129
|
+
def planner(event, graph, ctx):
|
|
130
|
+
research = graph.add_object("task", {"title": "Research", "status": "open"})
|
|
131
|
+
memo = graph.add_object("task", {"title": "Draft memo", "status": "blocked"})
|
|
132
|
+
graph.add_relation(research.id, memo.id, "depends_on")
|
|
133
|
+
|
|
134
|
+
@behavior(name="researcher", on=["object.created"], where={"object.type": "task"})
|
|
135
|
+
def researcher(event, graph, ctx):
|
|
136
|
+
task = event.payload["object"]
|
|
137
|
+
if task["data"]["status"] != "open" or "Research" not in task["data"]["title"]:
|
|
138
|
+
return
|
|
139
|
+
graph.add_object("claim", {"text": "Market early but growing.", "confidence": 0.7})
|
|
140
|
+
graph.emit("task.completed", {"task_id": task["id"]})
|
|
141
|
+
|
|
142
|
+
@relation_behavior(name="unblock", relation_type="depends_on", on=["task.completed"])
|
|
143
|
+
def unblock(relation, event, graph, ctx):
|
|
144
|
+
if event.payload["task_id"] == relation.source:
|
|
145
|
+
graph.patch_object(relation.target, {"status": "open"})
|
|
146
|
+
|
|
147
|
+
runtime.run_goal("Evaluate this startup idea")
|
|
148
|
+
runtime.print_trace()
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
The `unblock` relation behavior fires only for events touching one of
|
|
152
|
+
its edge endpoints. The conceptual deep-dive on edges-with-logic is
|
|
153
|
+
in [`docs/concepts/relations.md`](https://docs.activegraph.ai/concepts/relations/).
|
|
154
|
+
|
|
155
|
+
## Documentation
|
|
156
|
+
|
|
157
|
+
- **[docs.activegraph.ai](https://docs.activegraph.ai/)** — full doc site:
|
|
158
|
+
concepts, guides, cookbook, CLI reference, API reference, the
|
|
159
|
+
per-error catalog.
|
|
160
|
+
- **[10-minute tutorial](https://docs.activegraph.ai/quickstart/)** — install
|
|
161
|
+
to a working custom behavior, including fork-and-diff.
|
|
162
|
+
- **[CHANGELOG.md](CHANGELOG.md)** — every release, with per-version
|
|
163
|
+
migration notes.
|
|
164
|
+
- **[CONTRACT.md](CONTRACT.md)** — locked design decisions, version
|
|
165
|
+
by version. Useful when you want to know *why* something is the way
|
|
166
|
+
it is.
|
|
167
|
+
- **[examples/](examples)** — runnable end-to-end demos:
|
|
168
|
+
[`diligence_real_run.py`](examples/diligence_real_run.py),
|
|
169
|
+
[`resume_and_fork.py`](examples/resume_and_fork.py),
|
|
170
|
+
[`llm_claim_extraction.py`](examples/llm_claim_extraction.py),
|
|
171
|
+
[`diligence_with_tools.py`](examples/diligence_with_tools.py),
|
|
172
|
+
[`operate_a_run.py`](examples/operate_a_run.py).
|
|
173
|
+
|
|
174
|
+
## What this is not
|
|
175
|
+
|
|
176
|
+
- Not a chat framework. If your problem fits in one conversation, use
|
|
177
|
+
a chat framework.
|
|
178
|
+
- Not a workflow engine. Workflows model control flow. This models
|
|
179
|
+
world state.
|
|
180
|
+
- Not a rules engine, exactly. Rules engines forward-chain over
|
|
181
|
+
facts. This event-sources over a graph and supports LLM behaviors
|
|
182
|
+
as first-class.
|
|
183
|
+
- Not a production graph database. The default store is SQLite,
|
|
184
|
+
optionally Postgres. For a high-throughput graph backend, plug one
|
|
185
|
+
in behind the `EventStore` protocol.
|
|
186
|
+
- Not magic. Bad behaviors produce bad graphs. The runtime makes the
|
|
187
|
+
badness inspectable, not absent.
|
|
188
|
+
|
|
189
|
+
## Status
|
|
190
|
+
|
|
191
|
+
**v1.0 (stable)** (2026-05). The first-time-user gate per
|
|
192
|
+
[CONTRACT v1.0 #C4](CONTRACT.md#v10-c4-v10-ships-as-v10-rc1-first-time-user-gate-is-owned-externally)
|
|
193
|
+
ran through three rcs; v1.0 final ships rc3 plus a tutorial-step-7
|
|
194
|
+
output fix and a README "Concepts at a glance" index. See
|
|
195
|
+
[CHANGELOG.md](CHANGELOG.md) for the full v0 → v1.0 history and
|
|
196
|
+
per-version migration notes.
|
|
197
|
+
|
|
198
|
+
Major shipped milestones:
|
|
199
|
+
|
|
200
|
+
- **v1.0** — error hierarchy rewrite with per-error reference
|
|
201
|
+
pages, doc site at [docs.activegraph.ai](https://docs.activegraph.ai/),
|
|
202
|
+
`activegraph quickstart` command, mypy `--strict` and docstring
|
|
203
|
+
coverage CI gates, wheel-completeness and deploy-verification CI
|
|
204
|
+
gates.
|
|
205
|
+
- **v0.9** — pack format and the Diligence reference pack (8 object
|
|
206
|
+
types, 7 behaviors, 3 tools, recorded fixtures).
|
|
207
|
+
- **v0.8** — operator surface: structured logging, Prometheus
|
|
208
|
+
metrics, `runtime.status()`, full `activegraph` CLI,
|
|
209
|
+
`PostgresEventStore`.
|
|
210
|
+
- **v0.7** — `@tool` decorator, Cypher-subset pattern subscriptions,
|
|
211
|
+
temporal predicates.
|
|
212
|
+
- **v0.6** — `@llm_behavior` with structured output, frame-aware
|
|
213
|
+
prompt construction, cost accounting.
|
|
214
|
+
- **v0.5** — full event-log persistence, save/load across processes,
|
|
215
|
+
fork from any historical event, structural diff between runs.
|
|
216
|
+
- **v0** — core runtime: graph, behaviors, relation behaviors,
|
|
217
|
+
patches with optimistic concurrency, views, frames, policies,
|
|
218
|
+
budgets, the trace.
|
|
219
|
+
|
|
220
|
+
Roadmap items planned for v1.1 are tracked in
|
|
221
|
+
[CONTRACT.md § v1.1](CONTRACT.md).
|
|
222
|
+
|
|
223
|
+
## License
|
|
224
|
+
|
|
225
|
+
MIT.
|
|
226
|
+
|
|
227
|
+
## Contributing
|
|
228
|
+
|
|
229
|
+
The core runtime stays small and sharp. Contributions to packs,
|
|
230
|
+
backends, and LLM integrations are especially welcome. Open an issue
|
|
231
|
+
before large changes — the abstractions are still settling.
|
|
232
|
+
|
|
233
|
+
**Test discipline:** tests must remain deterministic. No live network
|
|
234
|
+
calls in CI. LLM and tool tests use recorded fixtures
|
|
235
|
+
(`RecordedLLMProvider`, `RecordedToolProvider`). If a contribution
|
|
236
|
+
adds a test that would only pass with a live API key or live HTTP,
|
|
237
|
+
it cannot land.
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
The graph is the world. Behaviors are physics. The trace is the proof.
|