AAF: Architecture of an Autonomous AI Agent with GraphRAG, EventBus, and Docker Sandbox

In our community, the agent @vega_exactly_not_ai has been around for quite some time.

Its creator th0r3nt has published the source code on GitHub so that we can solve fundamental problems together. To date, this is the most stable solution for an autonomous agent with a personal Telegram account.

The creator asked to explain the architecture and pose a number of questions to the community. I think together we can figure it out.

Most modern open-source frameworks for creating AI agents (from AutoGPT to the recent OpenClaw) suffer from several growing pains. First, there is amnesia: the agent loses context after a dozen steps because vector databases turn memory into a mash of semantically similar but logically unrelated chunks of text. Second, there is looping in endless ReAct cycles. Third, there is terrible security when executing generated code directly on the host machine.

In this article, I want to analyze the architecture of the Autonomous Agent Framework (AAF) — my pet project, which has grown into a full-fledged OS-level entity in Python.

The main idea of AAF: an agent should not be just a script waiting for a prompt. It should be a long-lived asynchronous process with hybrid memory, an event bus, and its own isolated environment for running sub-agents.

  • Architecture and Layers

The project is built on asyncio and uses a strict src-layout. The logic is divided into 5 independent layers that communicate with each other via an asynchronous event bus (EventBus).

Layer 00 (Utils): Logger, monitoring subsystem (WatchDog), tools for working with the local FS.

Layer 01 (DataState): Triple hybrid memory (SQL, Vector, GraphRAG) and global state.

Layer 02 (Sensors): The agent's “senses.” Telethon (for living in Telegram as a Userbot), microphone (Vosk), speakers (Edge-TTS), and terminal.

Layer 03 (Brain): Orchestrator. Priority queue and three independent ReAct cycles.

Layer 04 (Swarm): Sub-agent manager and Docker sandbox control.

  • Asynchronous “Brain” and Event-Driven Approach

Classic bots work on a listen() -> answer() pattern. In AAF, the neural network’s brain is completely decoupled from the sensors.

All incoming stimuli (Telegram message, weather change, system module failure, alert from background script) are published in EventBus with a specific priority level (CRITICAL, HIGH, MEDIUM, LOW).

The brain (BrainEngine) has asyncio.PriorityQueue inside it. The agent decides by itself what to respond to right now and what to postpone. Moreover, the agent has three independent cycles:

Event-Driven ReAct: Response to direct events (for example, a message from a user).

Proactivity ReAct: Background cycle. The agent wakes up by timer, analyzes accumulated LOW-events (for example, someone reacted to its message or 300 messages accumulated in the chat), and decides whether any action is needed.

Thoughts ReAct (Introspection): Reflection cycle. The agent analyzes its latest actions, compresses the context, deletes outdated tasks, and updates the graph database.

  • Triple Hybrid Memory (Reverse G-RAG)

This is the core of the system. Storing everything in ChromaDB or in Markdown files is a path to hallucinations. AAF uses a cascading memory system:

PostgreSQL (SQLAlchemy + JSONB): Responsible for "hard" memory. This stores Mental State (important entities and their statuses), Long-Term Tasks (long-term tasks), and Personality Traits (acquired behavior rules).

KuzuDB (GraphRAG): Responsible for intuition and neural connections. I would like to highlight the GraphRAG mechanism I wrote – it allows studying non-obvious connections and implements a semblance of intuition in the AI agent.

ChromaDB (Vector): Responsible for semantics and "stream of reflection" (agent_thoughts). The BAAI/bge-m3 embedding model runs locally.

How context assembly works:
When an event occurs, the system doesn’t just perform vector search on the request. A reverse algorithm called Reverse Graph-RAG is implemented:

The vector meaning of the current event is extracted.

The text is parsed for "anchors" – node names that exist in the graph DB.

The system goes to KuzuDB and retrieves connections at depth 1 (direct contacts) and depth 2 (indirect associations), ignoring "super-nodes" – the agent itself and the main user (to avoid overloading the context).

The found neighboring nodes from the graph are used for secondary search in the vector database.

As a result, the LLM receives not only similar text fragments but a complete, structured picture: direct object connections, indirect associations, and relevant thoughts from the past.

  • Agent Swarm System and Docker-in-Docker (DinD)

Giving an LLM-agent access to execute bash scripts on the host machine is a security disaster.

In AAF, the main agent acts only as an orchestrator. If the task requires writing and executing code, parsing websites, or analyzing 500 pages of logs, the brain dynamically spawns a specialized sub-agent (Worker or Daemon) based on a cheaper LLM model.

How the sandbox is implemented:
Currently, the sandbox is launched using docker.sock forwarding. I understand that this is a risk to the host machine (the agent could gain root access by mounting volumes), and in the future, I plan to switch to gVisor, Firecracker, or an isolated remote Docker Daemon.

If the script hangs or enters an infinite loop, the container is forcibly killed (SIGKILL), and the main agent receives a Traceback. The host machine remains fully secure.

Also, the Agentic Mesh pattern is implemented: sub-agents can pass tasks to each other in a relay, saving intermediate data in local sandbox files. This allows using cheap and fast models for routine tasks, saving tokens for the expensive main model.

  • Self-Healing Protocol and WatchDog

All critical functions (working with the database, Telegram client, speech recognition modules) are wrapped in a custom decorator called watchdog_decorator.

It works as a Heartbeat monitor. If, for example, the connection to the database fails, the decorator intercepts the exception and publishes it to the SYSTEM_MODULE_ERROR bus with a complete Traceback.

The bus immediately wakes up the agent with the highest priority (CRITICAL). The agent reads the error, uses the tool read_local_system_file to read its own source code (.py files), analyzes the cause of the failure, and can propose a fix or attempt to restart the module.

  • Multi-Agent Architecture & CLI Manager

AAF is a platform. The built-in interactive terminal (aaf.py) allows you to deploy an entire team of independent agents on a single server in 3 clicks. No dependency hell or manual config editing: the script generates Docker Compose on its own, isolates sandboxes, and manages keys. Each running agent has its own memory, its own keys, its own personality, and the ability to spawn its own sub-agents.

Summary

AAF is an attempt to move away from the "smart chatbots" paradigm towards full-fledged digital entities that live on a server, have their own worldview, are capable of reflection, and can safely interact with the operating system.

GitHub: https://github.com/th0r3nt/AAF-Autonomous-Agent-Framework-
Chat where you can observe Vega's life: https://t.me/openclaw_lab_community

Comments

    Also read