# How I Fixed Hallucinations by Switching from AGENTS.md to AGENTS.db

> Source: <https://dev.to/0x1brahim/how-i-fixed-hallucinations-by-switching-from-agentsmd-to-agentsdb-2ch1>
> Published: 2026-07-21 14:01:18+00:00

Before I dive in, a bit of background on how our agentic workflow at **Exam Intelligence** for deep analysis and notes generation works...

Initially, I tried to create a complete end-to-end LangGraph workflow. Except, things always ran into unexpected bugs caused by external factors like missing PDFs, being unable to find papers, failing to parse them, or agents returning 503 errors or broken JSONs.

At that point, it looked like I needed to build an entire coding agent just to handle the edge cases.

Instead of a master workflow, I switched to creating CLI tools that a coding agent can use.

If anything breaks, I decided on 3 levels of fixes:

Unaware of the standard `AGENTS.md`

naming conventions, I initially chose this setup:

`instructions.md`

: Informed the agent about the entire workflow, architecture, and how it should execute it.`memory.md`

: A persistent cross-session memory for the agent, mainly storing what bugs/problems it faced and how it fixed them.`workflow_checkpoints.db`

: A SQLite3 database used as temporary storage for the workflow, which is later pushed to PostgreSQL (used by our Django app) after quality checks to ensure production isolation.The agent started right, but when the time came to migrate the notes data and stuff to the Django database, it completely broke.

My workflow had a `migrate.py`

CLI tool which it could call to easily do the job (mentioned in `instructions.md`

), but it started using inline Python, always made syntax errors, migrated the data with broken formatting, and sometimes entirely skipped migrating certain tables.

So after witnessing multiple failures, I made the following changes:

`agents.db`

Here is the schema layout:

```
sqlite> .schema
CREATE TABLE instructions (
    id INTEGER PRIMARY KEY,
    step_order INTEGER NOT NULL,
    title TEXT NOT NULL,
    objective TEXT NOT NULL,
    actions TEXT NOT NULL,
    tools TEXT NOT NULL,
    success_criteria TEXT NOT NULL,
    created_at TEXT NOT NULL
);

CREATE TABLE memories (
    id INTEGER PRIMARY KEY,
    title TEXT NOT NULL,
    step TEXT NOT NULL,
    tldr TEXT NOT NULL,
    problem TEXT NOT NULL,
    fix TEXT NOT NULL,
    created_at TEXT NOT NULL
);
```

`instructions`

table`instructions.md`

. It gave the agent isolated, step-by-step instructions focused on strict objectives, what specific actions it must take, what CLI tools it has access to, and a clearly defined definition of what success looks like.`memories`

tableI pre-seeded the memories table with everything that went wrong in the previous runs and what the agent should have done in those instances using **synthetic memories**.

The agent was instructed to go step-by-step over the `instructions`

table. For each step, it queries the `memories`

table (just fetching the `tldr`

) as a brief on what needs to be done, how to do it, and what can possibly go wrong. If it encounters a new issue, it just adds that to memories.

Those changes allowed me to audit what the agent intends to do (the plan) and insert fixes if any. It allowed for hierarchical querying of instructions and bugs, and completely fixed the previous issues.

While I prompted the agent as a quick fix to just read the database (telling it when to do it), a more reliable way would be to just edit the harness to insert the right instructions and memories—saving more tokens on SQL queries per step.

Using the PI coding agents harness as the orchestrator adds flexibility, but it makes things way too unpredictable. Despite the flow being mostly hierarchical, I'm now stuck asking it to do a full run, catching hallucinations, and updating memories...
