SkillAgentSearch skills...

Engram

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

Install / Use

/learn @Mink026/Engram
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

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 | 简体中文

Related Skills

View on GitHub
GitHub Stars25
CategoryDevelopment
Updated14h ago
Forks0

Languages

Python

Security Score

90/100

Audited on Apr 6, 2026

No findings