The Problem

Developers who want an out‑of‑the‑box autonomous LLM agent often spend hours wiring memory, scheduling, and external tool integrations. The effort is amplified when the codebase is monolithic, hard to test, and fragile to small changes.

What This Does

babyagi3 supplies a ready‑made loop: input → LLM → action → execution → output. The core lives in main.py (entry at line 120) which boots the agent, loads config.yaml, and dispatches to the Agent class in agent.py. Tool implementations live under tools/ (34 files) and are registered via tools/__init__.py (the hub module with 29 dependents). Persistent memory is handled by memory/store.py (2066 lines, 137 functions, DB + crypto ops) and memory/embeddings.py. Scheduling, background jobs, and webhook handling are in scheduler.py and server.py. Send/receive channels (email, SendBlue, voice) are in listeners/ and senders/.

How It Is Wired

Execution starts in main.py:120 → calls run_all_channels → schedule_post_init_tasks. The shortest external side‑effects are:

  • Filesystem – INIT_STATE_FILE.unlink during post‑init.
  • Network – httpx.get in execute → fn (e.g., fetching remote content).
  • Database – self.conn.commit in run → log_message → create_event.

Key functions with the widest blast radius:

  • tool_error (called from 47 places) – defined in tools/__init__.py.
  • Schedule (46 callers) – defined in scheduler.py.
  • now_iso (38 callers) – utility in utils/.

memory/store.py is the primary persistence layer (reads/writes DB, encrypts data) and is invoked by Agent.execute, Agent.check_health, and the metrics collector. tools/__init__.py is the hub; any change ripples to 29 modules, making it a stability hotspot. A circular import exists among metrics/__init__.py, agent.py, and memory/integration.py, which inflates the instability of those modules.

How To Use It

# Clone and install
git clone https://github.com/moses-y/babyagi3 && cd babyagi3
uv sync            # or: pip install -e .

# Provide an LLM key (pick one)
export ANTHROPIC_API_KEY="sk-ant-..."
# or
export OPENAI_API_KEY="sk-openai-..."

# Run the agent
python main.py

Configuration lives in config.yaml (owner name/email, optional channel keys) and can be overridden by the environment variables listed above. The setup wizard will prompt for missing values and store secrets in the system keyring.

Testing is available via uv run pytest -q (18 test files under tests/). CI runs on every push using the workflow in .github/workflows/ci.yml.

Real‑World Use

A small business could launch an internal assistant that auto‑summarizes incoming support emails, stores the summaries in memory/store.py, and schedules follow‑up reminders via scheduler.py. The assistant would call tools/optional/http_utils.py to fetch relevant KB articles and reply through senders/email.py.

Code Health & Issues

Repository hygiene – tests present, CI present, license present, no lockfile, committed secrets (tools/secrets.py).

Measured findings (static analysis):

  • HIGH – Import cycle (metrics/__init__.py, agent.py, memory/integration.py).
  • HIGH – Hub module (tools/__init__.py, tools/optional/http_utils.py).
  • HIGH – Oversized files (agent.py, memory/store.py, memory/learning.py).
  • HIGH – Duplicated code blocks across 18 files.
  • HIGH – Deep nesting (27 occurrences, e.g., agent.py).
  • MEDIUM – Broad exception handling (tools/optional/http_utils.py, tools/secrets.py, memory/learning.py).
  • MEDIUM – File open without context manager (tools/files/creators.py, tools/files/processor.py).

Repository‑level health (GitHub Actions):

  • HIGH – Pin actions to commit SHA (astral-sh/setup-uv@v4).
  • MEDIUM – Declare least‑privilege GITHUB_TOKEN.
  • MEDIUM – Add Dependabot / Renovate.
  • MEDIUM – Add dependency‑vulnerability scan.
  • LOW – Set workflow timeouts.

Dependency drift: croniter, openai, and e2b-code-interpreter are several major versions behind current releases.

The Bottom Line

babyagi3 delivers a functional autonomous agent with clear separation of memory, scheduling, and tool integration, but the codebase suffers from large, tightly coupled modules, circular imports, and several maintainability concerns. It is suitable for teams that need a quick prototype and are comfortable refactoring the hub and oversized files before production use.