Skip to main content

Agent Graph Framework — core graph primitives for symfonic

Project description

symfonic-core

Hierarchical Memory System for AI Agents

Overview

symfonic-core is a Python framework for building AI agents with persistent, structured memory. It implements a five-layer Hierarchical Memory System (HMS) inspired by cognitive science: Semantic, Episodic, Working, Prospective, and Procedural memory -- all backed by Postgres for durable persistence.

The framework goes beyond simple retrieval-augmented generation. On every query, it hydrates context from multiple memory layers, runs spreading activation across the knowledge graph to surface related facts, executes the LLM, extracts structured memory operations from the response, and consolidates them back into the appropriate layers. A Deep Sleep consolidation engine strengthens recurring knowledge, prunes stale nodes, and generates meta-nodes from clusters -- running as a nightly task or on manual trigger.

symfonic-core ships a set of cooperating subpackages in a single distribution:

Subpackage Role
symfonic.core Graph execution engine: nodes, edges, DI container, tools, streaming
symfonic.memory 5-layer HMS: episodic, semantic, procedural, prospective, working
symfonic.agent Orchestration: wires core + memory, exposes SymfonicAgent, FastAPI bridge
symfonic.knowledge Semantic knowledge retrieval (RAG) layer
symfonic.observability Cross-cutting metrics, cost tracking, and OpenTelemetry adapters
symfonic.tools Built-in tool integration adapters
symfonic.infra Infrastructure abstractions for external services
symfonic.diagnostics symfonic doctor — adopter-config audit
symfonic.cli Scaffolding CLI (symfonic init) and agent command line

Quick Start

Installation

pip install symfonic-core

With Anthropic provider and FastAPI support:

pip install "symfonic-core[anthropic,agent-api]"

symfonic-core is published on PyPI, so no extra index configuration is required.

Environment Variables

Variable Required Description
ANTHROPIC_API_KEY For real LLM Anthropic API key
POSTGRES_DSN For persistence PostgreSQL connection string
MONGODB_URI Optional MongoDB URI for graph visualization secondary

Minimal Code Example

import asyncio
from symfonic.agent import SymfonicAgent, FrameworkTenantScope
from symfonic.core.testing import MockModelProvider

async def main() -> None:
    agent = SymfonicAgent(model_provider=MockModelProvider(response="Hello!"))
    scope = FrameworkTenantScope(tenant_id="acme")
    response = await agent.run("What do you know about us?", scope=scope)
    print(response.final_response)
    print(f"Memory entries used: {response.memory_entries_used}")
    print(f"Duration: {response.duration_ms:.0f}ms")

asyncio.run(main())

Supported Providers

symfonic-core ships with five model providers. Each is optional -- only install the package for the provider you need.

Provider Package Install Extra Thinking Streaming Limitations
Anthropic langchain-anthropic [anthropic] Yes (extended thinking) Yes Requires API key
OpenAI langchain-openai [openai] Partial (o1/o3 only) Yes No thinking blocks for GPT-4o
DeepSeek langchain-openai [deepseek] Yes (R1 reasoning) Yes Reasoning format differs from Anthropic thinking blocks -- ThinkingDeltaEvent may not capture all reasoning
Google Gemini langchain-google-genai [google] Yes (2.5 thinking) Yes Thinking format not yet standardized in LangChain
Ollama (local) langchain-ollama [ollama] No Yes No cloud API -- runs locally. No thinking support. Memory/speed depends on hardware
AnthropicOAuth (built-in) [anthropic] Yes Yes DEV/TEST ONLY — uses Claude Code OAuth token against a Claude Pro/Max subscription. Not suitable for multi-tenant production (no per-tenant billing, interactive token refresh).

AnthropicOAuthProvider lives in src/symfonic/core/oauth_provider.py and requires no ANTHROPIC_API_KEY. Use it for local development and running the full pipeline (autonomous learning, metacognition) against a real LLM without provisioning API credits. Never deploy it to production.

from symfonic.core.oauth_provider import AnthropicOAuthProvider
agent = SymfonicAgent(model_provider=AnthropicOAuthProvider())

Provider Usage

# Anthropic (default)
from symfonic.core.providers import AnthropicProvider
agent = SymfonicAgent(model_provider=AnthropicProvider())

# OpenAI
from symfonic.core.providers import OpenAIProvider
agent = SymfonicAgent(model_provider=OpenAIProvider())

# DeepSeek
from symfonic.core.providers import DeepSeekProvider
agent = SymfonicAgent(model_provider=DeepSeekProvider(api_key="sk-..."))

# Google Gemini
from symfonic.core.providers import GoogleProvider
agent = SymfonicAgent(model_provider=GoogleProvider())

# Local Ollama
from symfonic.core.providers import OllamaProvider
agent = SymfonicAgent(model_provider=OllamaProvider())

The Pentad -- 5 Memory Layers

Layer Purpose Backend Persistence
Semantic Stable knowledge graph -- facts, entities, relationships Postgres Graph (+ optional MongoDB secondary) Persistent
Episodic Timestamped interaction history and events Postgres Vector Persistent
Working Active reasoning context with 24h TTL thinking nodes Postgres Graph (short-TTL) Persistent
Prospective Future plans, reminders, scheduled triggers Postgres Graph Persistent
Procedural Learned skills, workflows, tool routing Postgres Graph + SkillRegistry Persistent

All five layers share the BaseMemoryStore protocol with a uniform write / retrieve / delete interface and strict per-tenant isolation via TenantScope.

v8.0 BREAKING — hierarchical TenantScope. TenantScope is now an arbitrary-depth, root-first path of ScopeLevel(kind, id) values (e.g. org → brand → conversation), not a fixed (tenant_id, sub_tenant_id) shape. A query at a path sees memories at its own path and every ancestor prefix and NEVER a sibling — prefix isolation is an always-on security boundary that closes cross-session bleed. The flat fields are retained and backward-compatible (computed off the path), so most adopters need no source change; bare TenantScope(tenant_id=...) still works but is deprecated — switch to the factories (root(...).child(...), from_path([...])). Opt-in scope-distance retrieval weighting blends ancestor memories down-weighted by hierarchy distance. See docs/concepts/hierarchical-tenant-scope.md, the examples/jarvio_reference/ demonstration, and the ## [8.0.0] migration guide in CHANGELOG.md.

Key Features

Every capability below is default-preserving — FrameworkConfig() reproduces pre-upgrade behaviour byte-for-byte. Adopt features one knob at a time. For a grouped walk-through with opt-in examples, see docs/FEATURES.md.

  1. Agent and PromptingSymfonicAgent + FrameworkConfig + DomainTemplate. Full HMS system prompt (9 sections, ~1800 tokens) or JIT mode (≤230 tokens). DomainTemplate.description reaches both prompts since v7.0.2 (capped by domain_description_max_chars). TOOL DISCIPLINE directive (v6.1.10) in both templates. v7.2 / Item 8: FrameworkConfig.context_strategy="jit"|"stratified" selects between the JITContextManager (~210-token prompt + reactive hydration) and StratifiedHMSContextManager (L0/L1/L2 layered prompt with inline hydration) via the new ContextManager protocol. Default None infers from the legacy jit_context flag (byte-identical pre-v7.2 behaviour). JIT mode auto-registers the hydrate_context tool on the agent so the LLM has a real on-demand memory escape hatch — no manual wiring needed. v7.2 / Item 9 (experimental): agent.register_interrupt() + agent.interrupt() generalise the ask_user pause/resume envelope to any named human-in-the-loop step (approvals, sign-offs, review gates) with a caller-supplied Pydantic payload. Same HMAC + scope-bound + single-use security envelope as ask_user. Gated by experimental_interrupt=True; ask_user keeps its dedicated codepath so the event stream stays byte-identical when only the built-in case is exercised. Guide.

  2. 5-Pentad Memory — Semantic (knowledge graph), Episodic (narrative log), Working (short-term with 24h TTL), Procedural (learned skills), Prospective (reminders). Five POST /api/v1/memories/{layer} endpoints (v6.1.4) plus GET / PATCH / DELETE. All tenant-scoped. Guide.

  3. Retrieval and Hydration — Spreading activation with N-hop BFS (hydration_max_hops, v7.0), importance threshold (hydration_threshold, v6.1.8), raw-turns cap (working_memory_raw_turns), STM summary (stm_summary_mode off/extractive/llm, v7.0), credential scrub (credential_patterns, v6.2). hydrate_context JIT escape hatch tool.

  4. Tooling and Routingtool_trigger_keywords for in-prompt manifest filtering (v6.1.8), tool_routing_mode for wire-level tools= narrowing (v7.0.1, observe/enforce), always_include_tools (v7.0.3), jit_manifest_token_budget for JIT manifest compression (v6.2 T04), lazy_tooling for procedural-memory-driven tool selection. v7.1.x / Item 6 (experimental): @symfonic_tool(scope=..., routing_mode=..., visibility=...) decorator derives the tool's JSON schema from type hints + docstrings and threads the symfonic metadata into the existing ToolRegistry — zero manifest plumbing. Async-generator tools yield ToolProgressEvents (v7.1.x / Item 7) for streaming progress. Gated by experimental_tool_decorator=True. v7.1.x / Item 10: otel_enabled=True ships an opt-in OpenTelemetry exporter (bridge-adapter pattern, lazy import) that emits symfonic.run root spans + node/llm/tool/interrupt child spans. Zero opentelemetry modules loaded when disabled. Guide 6 / Guide 7.

  5. Intent ClassificationIntentClassifier labels each turn knowledge/action/ambiguous before hydration via deterministic verb+keyword matching (zero LLM cost, v7.0). Unicode-aware + NFC-normalised tokenizer (v7.0.3) — Spanish / German / French / Portuguese / Chinese / Japanese classify correctly. intent_filter_mode off/observe/enforce.

  6. Fabrication Detection — Cross-reference detector flags UUIDs, kv pairs (task_id=abc), verb claims ("I spawned X"), and context-anchored short-hex identifiers (v7.0.3) that are not grounded by a fired tool. Per-verb tool grounding (_VERB_TO_TOOL_HINTS). Language-agnostic intent_action_no_tool finding (v7.0.6) fires when the IntentVerdict says "action" and zero tools ran — catches Spanish / French / German / Portuguese fabrications the English-only verb regex misses. Modes: off / observe / revise / refuse, gated by fabrication_refuse_min_confidence (default 0.8). Typed FabricationDetectedEvent (v7.0.7) carries run_id, action_taken, refuse_threshold, max_finding_confidence, and 240-char draft / replacement previews so SRE dashboards can tune the threshold from telemetry without recomputing the verdict. Guide.

  7. Consolidation (Deep Sleep)SleepConsolidator runs 11 distinct phases: strengthen, cooccurrence, tag_risk, pending_edges, prune_orphans, meta_nodes, soul_corrections, working_ttl, decay_importance, episodic_summary, synthetic_links, procedural_promotion. Three entrypoints: quick_nap (every-N-turns), run (full roster), nightly_nap (v7.0 T12, operator-scheduled). ConsolidationReport.phases_run for observability. v7.2 / Item 12: opt-in entity_links phase (enable_entity_linker) autonomously mints Entity:<kind>:<surface> semantic nodes and MENTIONS edges from natural-language episodic content, so spreading activation crosses months/years without manual semantic.link() plumbing. Pluggable extractor (regex default, spacy / llm opt-in via extras). Guide.

  8. ObservabilityLLMStartEvent (engine view), LLMPreCallEvent (wire view, v6.1.7), LLMEndEvent (response), ToolRoutingDecisionEvent (v7.0.1), ExtensionEvent for intent / fabrication. Optional hooks are hasattr-gated so legacy handlers cost nothing. TokenBudgetTracker + PostgresBudgetStore for multi-replica correctness. Episodic telemetry sink (episodic_telemetry_sink, v6.1). Guide.

  9. Security and Multi-tenancyFrameworkTenantScope enforced at the backend level. create_agent_router() raises RuntimeError in production without set_tenant_auth_verifier(). Three-tier credential scrubbing (v6.1.9): extraction directive + write-time + read-time. Tunable patterns via credential_patterns (v6.2 T01). GDPR Article 17 + 20 endpoints. Guide.

  10. Streamingstream_text() (clean strings), stream_typed() (typed events), stream() (raw StreamChunk). ExtractionFilter + CitationFilter strip <MEMORY_EXTRACT> / [semantic] tags safely across chunk boundaries. Full event taxonomy in concepts/streaming-events.md.

  11. Domain PluginsBaseDomainPlugin + DomainTemplate with core_preferences, soul_schema, tool_manifest, tool_trigger_keywords, identifier_keys (v7.0 fabrication lexicon), monitoring. SRE starter (symfonic init --components sre-starter) bundles 4 tools + 4 safety rails as a reference implementation. Guide / SRE Starter.

Configuration Matrix

Every FrameworkConfig field grouped by cluster with default value. This table is the source of truth for the v7.0.3 surface; verified against src/symfonic/agent/config.py. See docs/FEATURES.md for opt-in examples and docs/guides/migrate-6x-to-7x.md for the v7.0 upgrade path.

Cluster Field Default
Agent enable_hms_prompt False
Agent jit_context False
Agent memory_extract_cadence 1
Agent activation_log_mode "always"
Agent domain_description_max_chars (2000, 400)
Agent reflection_prompt None
Agent self_reflection False
Memory enabled_layers {working,episodic,semantic,procedural,prospective}
Memory auto_hydrate True
Memory auto_consolidate True
Retrieval spreading_activation True
Retrieval hydration_max_hops 0
Retrieval hydration_threshold 0.0
Retrieval working_memory_raw_turns None
Retrieval stm_summary_mode "off"
Retrieval credential_patterns None
Tooling lazy_tooling True
Tooling tool_routing_mode "off"
Tooling always_include_tools ("hydrate_context",)
Tooling jit_manifest_token_budget 0
Intent intent_filter_mode "off"
Fabrication fabrication_check_mode "off"
Fabrication fabrication_refuse_min_confidence 0.8
Consolidation quick_nap_interval 0
Consolidation nightly_nap_enabled False
Consolidation nightly_nap_cron "0 3 * * *"
Consolidation phase1_spreading_weight 0.5
Consolidation synthetic_link_min_co_count 2
Consolidation promotion_min_pattern_count 3
Consolidation promotion_recency_days 30

Additional fields (episodic summarization, metacognition, scheduler, skill auto-approve) are documented in docs/FEATURES.md to keep this matrix at the 30-row cap.

Scaffolding (symfonic init)

symfonic init <name> --components <list> generates a production-ready project. Available components: fastapi, webapp, docker-compose, postgres, mongodb, chats, billing, sre-starter (9 total).

The sre-starter component adds an opt-in SRE assistant domain plugin:

  • 4 tool stubs: DbAnalysisTool, AwsStatusTool, LogSearchTool, ErrorTriageTool
  • 4 CorePreferences enforcing safety rails (no destructive ops without confirmation, cite evidence)
  • Dev memory seed script and smoke tests
symfonic init my-agent --components fastapi,webapp,docker-compose,sre-starter

sre-starter and the default starter domain plugin are mutually exclusive.

API Endpoints

The FastAPI router (create_agent_router) mounts these endpoints:

Method Path Description
POST /chat Synchronous agent execution, returns AgentResponse
POST /stream SSE streaming, yields StreamChunk events
POST /stream/typed SSE stream of typed events (TextDeltaEvent, ToolCallStartEvent, MemoryExtractedEvent, ConsolidationScheduledEvent, etc.) — see Streaming Events
GET /chats List chat sessions for tenant
GET /memories/status Memory block status per label
GET /memories List all semantic memory nodes
POST /memories/semantic Create a permanent fact node (v6.1.4)
POST /memories/episodic Create a timestamped narrative event (v6.1.4)
POST /memories/procedural Create a skill / workflow node (v6.1.4)
POST /memories/working Push an entry to the working-memory buffer (v6.1.4)
POST /memories/prospective Create a trigger / reminder (v6.1.4)
PATCH /memories/{node_id} Update a memory node
DELETE /memories/{node_id} Delete a memory node
GET /procedures List procedural skills (approved by default; ?status=draft|rejected|all)
GET /procedures/drafts List skills pending human review
POST /procedures/{id}/approve Approve a draft skill (makes it active)
POST /procedures/{id}/reject Reject a draft skill
PATCH /procedures/{node_id} Update a procedure
POST /procedures/{node_id}/toggle Toggle procedure active flag
POST /procedures/deduplicate SemanticMerge deduplication
POST /memory/consolidate Trigger Deep Sleep consolidation
GET /graph/nodes/{id}/neighborhood BFS neighborhood traversal
GET /graph/paths Shortest path between nodes
GET /edges List all edges for tenant
POST /edges Create edge between nodes
DELETE /edges/{edge_id} Delete an edge
GET /graph/clusters Cluster projection by label prefix
GET /memories/{node_id} Retrieve a single memory node
GET /procedures/{node_id} Retrieve a single procedure node
DELETE /procedures/{node_id} Delete a procedure node (cascades edges)
GET /tenants/me/export GDPR Art. 20 — export all tenant data as JSON (rate-limited: 5/day)
DELETE /tenants/me/data GDPR Art. 17 — erase all tenant data (requires ?confirmation=DELETE-<tenant_id>, rate-limited: 1/hour)
GET /billing/usage Token usage for today + current month
GET /billing/limits Budget ceilings + headroom for tenant
GET /admin/audit Paginated audit log (admin/org-owner scoped) †
POST /admin/tenants/{tenant_id}/budget Set / update tenant daily + monthly budget limits †
GET /admin/tenants/{tenant_id}/usage Read tenant's current usage window †
POST /admin/tenants/{tenant_id}/budget/reset Zero the in-memory budget tracker for a tenant †

† Admin endpoints require JWT role="admin" OR org-owner membership (Membership.role == "owner"). Non-admin callers receive 403 Forbidden.

The full demo (examples/full_demo/) adds additional endpoints for metrics, traces, analytics, graph visualization, billing, sub-agent findings, and scheduled tasks.

Architecture

The Thalamic pipeline runs four stages per turn:

Query --> SymfonicAgent.run() / stream_typed() / stream_text()
           |
           +--> 1. Triage
           |      |-- IntentClassifier (deterministic, zero-LLM)
           |      |     verdict: knowledge / action / ambiguous
           |      |-- apply_tool_routing
           |      |     narrow tools= payload per intent verdict
           |      '-- emit ExtensionEvent(intent_classified) + ToolRoutingDecisionEvent
           |
           +--> 2. Hydrate
           |      |-- Retrieve from enabled layers (semantic/episodic/procedural/prospective)
           |      |-- SpreadingActivation.expand() N-hop BFS with decay
           |      |-- Scrub credential-shaped keys (_scrub_credential_keys)
           |      '-- Format context string with activation_log metadata
           |
           +--> 3. LLM Execution (AgentRuntime / LangGraph)
           |      |-- HMS system prompt (9 sections, with TOOL DISCIPLINE)
           |      |-- Or JIT prompt (<=230 tokens + hydrate_context escape hatch)
           |      |-- LLMStartEvent (engine view) / LLMPreCallEvent (wire view)
           |      |-- EventTranspiler: ThinkingDelta / TextDelta / ToolCall events
           |      |-- ExtractionFilter + CitationFilter strip blocks safely
           |      '-- LLM generates response + MEMORY_EXTRACT block
           |
           +--> 4. Fabrication check + Consolidation
                  |-- Fabrication detector cross-references identifiers/verbs
                  |     against tool results + hydrated context
                  |-- refuse/revise modes can replace draft
                  |-- _consolidate (background): parse ops, scrub creds, persist
                  |-- Write thinking nodes to Working memory (24h TTL)
                  |-- Write episodic turn summary (with telemetry sink)
                  '-- quick_nap every N turns / nightly_nap per scheduler

See docs/concepts/architecture.md for the full component diagram.

Examples

Example Description
examples/tui_chat/ Zero-infra interactive TUI playground. Runs with MockModelProvider (no API key, no DB). Ideal for exploring the agent loop and streaming locally. See examples/tui_chat/README.md.
examples/full_demo/ Full-stack demo: Postgres, MongoDB, web UI (chat, Memory Vault, graph viz, billing, analytics).

Demo

Run the full interactive demo with Postgres, MongoDB, and web UI:

cd examples/full_demo
# Start infrastructure
docker compose up -d  # Postgres + MongoDB
# Install dependencies
pip install -e ".[agent-api,anthropic,mongodb]"
# Run server (mock mode or with ANTHROPIC_API_KEY)
python -m examples.full_demo.server

Open http://localhost:8000 for the web UI with chat, Memory Vault, graph visualization, workflows, analytics, and observability panels.

See examples/full_demo/README.md for details.

Documentation

Start here

Document Purpose
Feature Catalog One-page reference for all 11 capability clusters with opt-in examples
Changelog User-facing changes by release
Migration 6.x → 7.x Upgrade path including the enable_hms_prompt kwarg removal

Guides (level-up path)

Guide Description
01 Quickstart 10-line agent with MockModelProvider
02 Memory Persistence Postgres + pgvector, 5 memory layers, tenant isolation
03 Streaming & Callbacks Three stream APIs, LLMPreCallEvent, ToolRoutingDecisionEvent
04 Plugins & Domains DomainTemplate, BaseDomainPlugin, guardrails, SOUL schema
05 Production Docker stack, Celery beat, auth gate, credential scrub
06 Lazy Tooling Procedural-memory-driven tool selection
07 Intent & Tool Routing Intent classifier, tool_routing_mode, i18n tokenizer
08 Fabrication Detection Detector patterns, confidence thresholds, deployment stance
09 Consolidation & Deep Sleep 11 phases, quick_nap vs nightly_nap, decay exemptions
SRE Starter SRE domain plugin with 4 real-backend tools

Concepts

Document Description
Architecture Thalamic pipeline, component diagram, multi-tenant isolation
Memory (HMS) 5 layers, hydration, spreading activation
Agent Layer SymfonicAgent, AgentResponse, streaming events
Capabilities & DI Protocol-based dependency injection
Streaming Events Event taxonomy, ordering guarantees
Deep Sleep Phases Phase reference
Autonomous Learning Episodic → Phase 12 → human review pipeline
Examples Walk-through of curated examples
Research Foundations Academic basis

Research Foundations

symfonic-core's architecture is grounded in peer-reviewed research on agent memory systems. See Research Foundations for the academic basis and where symfonic innovates beyond the literature.

Testing

pytest tests/ -q
# With coverage
pytest --cov=symfonic.core --cov=symfonic.memory --cov=symfonic.agent --cov-report=term-missing

6200+ tests covering unit, integration, contract, and release-gate layers.

Development

git clone <repo-url> && cd symfonic-core
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"

# Type checking
mypy src/

# Linting
ruff check src/ tests/

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

symfonic_core-8.7.5.tar.gz (2.3 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

symfonic_core-8.7.5-py3-none-any.whl (1.1 MB view details)

Uploaded Python 3

File details

Details for the file symfonic_core-8.7.5.tar.gz.

File metadata

  • Download URL: symfonic_core-8.7.5.tar.gz
  • Upload date:
  • Size: 2.3 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for symfonic_core-8.7.5.tar.gz
Algorithm Hash digest
SHA256 59a59c78dc9b6a70a1c7eda5a068b7ad69cfb14fe93a42816ec2a30847581a2e
MD5 202095a55f5fd017e1c13707ef0966f7
BLAKE2b-256 009f7ab7ee11634a39055f69e48fb527f125849b6180900f7a2e9325e6c95070

See more details on using hashes here.

File details

Details for the file symfonic_core-8.7.5-py3-none-any.whl.

File metadata

  • Download URL: symfonic_core-8.7.5-py3-none-any.whl
  • Upload date:
  • Size: 1.1 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for symfonic_core-8.7.5-py3-none-any.whl
Algorithm Hash digest
SHA256 32afff53da9be03db57a22452d088cffb2986942dd359562fb0cc17c33aae25c
MD5 a51c4819eecd1eab04d49d3e2cf3e4a7
BLAKE2b-256 571594e16f2d4ec8561b5d5a4ee76fe9e5912c7cec3519122e2ee3e42ba60e9e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page