Skip to content

Mink026/Engram

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

engram

Languages: English | 简体中文

A text-only conversational agent with a Planner → Manager → Executor pipeline (LangGraph), optional Neo4j + Graphiti memory graph, and a React + Vite frontend. Secrets live in .env, not in code.

Engram (neuroscience): the physical trace of a memory in the brain—aligned with “dialogue agent + persistent memory graph.”

Screenshots

Chat (streaming + sessions) Memory graph (Neo4j / vis-network)
Chat UI Memory graph

Features

  • Agent workflow: Planner (JSON mode structured plan) routes work to role-based executors; Manager schedules steps; executors call the LLM (streaming for replies).
  • Chat UI: SSE streaming, session list, history restored from the server after refresh.
  • Memory graph: Optional Graphiti episodes + Neo4j; vis-network page embeddable from the frontend.
  • Persistence: DATABASE_URL or default SQLite at backend/data/engram.db.
  • Extensible roles: executors_config.yaml + optional Python executor classes.

Requirements

  • Backend: Python 3.11+ recommended, uv
  • Frontend: Node 18+ / npm
  • Optional: Neo4j for the memory graph; OpenAI-compatible LLM API

Repository layout

engram/
├── docs/static/screenshots/ # UI screenshots (README)
├── backend/                 # FastAPI, uv
│   ├── main.py              # Entry, port 5000 by default
│   ├── config.py            # Loads .env
│   ├── executors_config.yaml
│   ├── core/                # planner, manager, base_executor, state
│   ├── executors/           # registry + custom executors
│   ├── tools/               # @tool definitions → ALL_TOOLS
│   ├── tools_lib/           # TOOL_REGISTRY, get_tools_by_names
│   ├── graph/               # LangGraph workflow
│   ├── services/            # agent SSE, Graphiti, session store
│   ├── routes/              # /api/chat, /api/kg/*, sessions
│   ├── models/              # SQLAlchemy (conversations / messages)
│   └── templates/           # kg_graph.html (vis-network)
└── frontend/                # React (Vite), port 3000
    └── src/pages/           # ChatPage, MemoryGraphPage

Quick start

Backend

cd engram/backend
cp .env.example .env
# Edit .env: LLM_API_KEY, LLM_BASE_URL, LLM_MODEL, etc.

uv sync
# Production-style (no auto-reload on file changes)
uv run python main.py
# Dev hot reload:
#   UVICORN_RELOAD=1 uv run python main.py
#   # or: uv run uvicorn main:app --reload --port 5000
  • API base: http://localhost:5000
  • OpenAPI: http://localhost:5000/docs

Frontend

cd engram/frontend
npm install
npm run dev
  • App: http://localhost:3000 (Vite proxies /api to localhost:5000 in dev)

Conversation & session HTTP API

Method Path Description
GET /api/sessions sessions (ids) + conversations (session_id, title, updated_at)
GET /api/sessions/{session_id}/messages Full message list for reload/hydration
DELETE /api/sessions/{session_id} Delete server-side session + messages

If DATABASE_URL is unset, SQLite is used automatically; history still persists.

Environment variables (backend/.env)

Variable Description Required
LLM_API_KEY API key Yes
LLM_BASE_URL OpenAI-compatible base URL Yes
LLM_MODEL Chat model name Yes
GRAPHITI_LLM_MODEL Model for Graphiti extraction (default gpt-4o) No
GRAPHITI_EMBEDDING_MODEL Embedding model name No
NEO4J_URI e.g. bolt://localhost:7687 (empty disables graph writes) No
NEO4J_USER Default neo4j No
NEO4J_PASSWORD Password No
USER_ID Graphiti group_id (default 1) No
DATABASE_URL SQLAlchemy URL; empty → ./data/engram.db No
HOST / PORT Bind address (default 0.0.0.0:5000) No
UVICORN_RELOAD 1 / true to enable reload with python main.py No

Database URL examples

Engine DATABASE_URL Extra dependency
SQLite (default) (omit)
PostgreSQL postgresql+psycopg2://user:pass@host:5432/db uv add psycopg2-binary
MySQL mysql+pymysql://user:pass@host:3306/db uv add pymysql

Custom executors

Tool functions (agent_platform-style: code-first presets)

  1. Declare @tool functions under backend/tools/ and register them via tools/__init__.py (_TOOL_MODULES).
  2. In tools_lib/__init__.py, define named sets the same way as GENERAL_TOOLS / RESEARCHER_TOOLS in agent_platform:
GENERAL_TOOLS = get_tools_by_names(["get_current_time", "calculate"])
TOOL_PRESETS = {"general": GENERAL_TOOLS, "empty": EMPTY_TOOLS, ...}
  1. Python executors: implement get_tools()return GENERAL_TOOLS (see executors/example_executor.py).
  2. YAML-only executors: set tool_preset: general (or empty, analyst, …) instead of listing every tool name.

Optional tools: [name, ...] in YAML still overrides presets / class get_tools() when you need an explicit exception.

Use tools_lib.list_registered_tool_names() and list_tool_presets() for debugging.

A. YAML-only (no code)

Edit backend/executors_config.yaml (optional tools as above). Restart the backend. The Planner reads role_key values from the registry.

B. Python class

  1. Add e.g. backend/executors/researcher.py implementing BaseExecutor (role_name, system_prompt, get_tools()), or rely on YAML tools to inject shared tools without custom get_tools.
  2. Register in YAML:
- role_key: researcher
  name: Researcher
  desc: Tasks that need search or structured gathering
  python_class: executors.researcher.ResearcherExecutor

Restart the backend.

HTTP API summary

POST /api/chat

SSE stream. Body:

{ "query": "Hello", "session_id": "uuid-here" }

Events include: user_message, todo_list, summary, tool_call, tool_result, answer_delta, answer, error, end.

GET /api/kg/page

HTML page for the memory graph (e.g. iframe). Uses USER_ID as default group_id when not overridden.

GET /api/kg/graph

JSON nodes/edges for the graph viewer.


Languages: English | 简体中文

About

基于 Planner–Manager–Executor 的文本 Agent;Executor 支持 YAML / Python 高度自定义;可选 Neo4j+Graphiti 记忆图谱;FastAPI + React。

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors