> ## Documentation Index
> Fetch the complete documentation index at: https://phidatainc.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Self-correcting agents

> Save diagnosed query errors as learned knowledge and retrieve the corrections on later runs.

Use the Learning Machine to save diagnosed query corrections and retrieve them for related requests.

```bash theme={null}
uv pip install "agno[openai,pgvector,psycopg,sql]"
```

```python theme={null}
from agno.agent import Agent
from agno.db.postgres import PostgresDb
from agno.knowledge.knowledge import Knowledge
from agno.learn import LearningMachine
from agno.models.openai import OpenAIResponses
from agno.tools.sql import SQLTools
from agno.vectordb.pgvector import PgVector

db_url = "postgresql+psycopg://ai:ai@localhost:5532/ai"

db = PostgresDb(db_url=db_url)
knowledge = Knowledge(
    vector_db=PgVector(table_name="agent_learnings", db_url=db_url),
)

agent = Agent(
    id="data-analyst",
    model=OpenAIResponses(id="gpt-5.5"),
    db=db,
    tools=[SQLTools(db_url="postgresql+psycopg://readonly@warehouse/analytics")],
    learning=LearningMachine(knowledge=knowledge, decision_log=True),
    instructions=(
        "Before writing SQL, call search_learnings with terms from the request and "
        "apply relevant corrections. "
        "When a query errors, diagnose the cause. Call save_learning for a "
        "reusable correction. Call log_decision when you change the query shape."
    ),
)
```

Passing `knowledge` to `LearningMachine` enables the Learned Knowledge store. It uses `AGENTIC` mode by default, so the model calls `save_learning` when it finds a reusable correction. `decision_log=True` also selects `AGENTIC` mode and adds the `log_decision` and `search_decisions` tools. A decision is saved only when the model calls `log_decision`.

## The loop

1. The agent writes SQL and runs it.
2. It errors, or returns a number a human flags as wrong.
3. The agent diagnoses the cause (wrong column, stale table, a join that double-counts).
4. The fix is saved according to the configured learning mode.
5. On the next similar request, the agent calls `search_learnings` before generating SQL.

In `AGENTIC` mode, retrieval occurs when the model calls `search_learnings`. The instruction in this example makes that search part of the query workflow.

## Choose how learning happens

Each store has its own mode. Choose explicit tool calls, background extraction, or human approval based on the correction.

```python theme={null}
from agno.learn import LearnedKnowledgeConfig, LearningMachine, LearningMode

always_agent = Agent(
    id="data-analyst",
    model=OpenAIResponses(id="gpt-5.5"),
    db=db,
    learning=LearningMachine(
        knowledge=knowledge,
        learned_knowledge=LearnedKnowledgeConfig(mode=LearningMode.ALWAYS),
    ),
)
```

| Mode      | Behavior                                                  | Use for                                                                                               |
| --------- | --------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `ALWAYS`  | Background extraction from the pre-model message snapshot | Corrections in the current user input, plus prior user and assistant messages when history is enabled |
| `AGENTIC` | The agent decides what to save with explicit tools        | Nuanced domain insights                                                                               |
| `PROPOSE` | The agent proposes, a human approves before it persists   | Anything that changes how numbers are computed                                                        |

`ALWAYS` schedules background extraction after run messages are prepared and before the main model call. With the default `add_history_to_context=False`, this example supplies the current user message. Set `add_history_to_context=True` to include prior user and assistant messages in later snapshots. The extractor ignores system messages, tool calls, and tool results. It may decide there is nothing worth saving.

## Audit what it learned

Inspect the Learned Knowledge store for saved corrections and the Decision Log for recorded query-shape decisions.

```python theme={null}
lm = agent.learning_machine

# What the agent has learned about the warehouse:
lm.learned_knowledge_store.print(query="MRR")

# The audit trail of why a query shape changed:
lm.decision_log_store.print(agent_id=agent.id, limit=5)
```

| Store             | Why a data agent wants it                   |
| ----------------- | ------------------------------------------- |
| Learned Knowledge | Corrections that transfer across users      |
| Decision Log      | An audit trail of why a query shape changed |

## Next steps

| Task                        | Guide                                                               |
| --------------------------- | ------------------------------------------------------------------- |
| Feed it curated context too | [Grounding in context](/use-cases/data-agents/grounding-in-context) |
| Gate writes behind approval | [Safe data access](/use-cases/data-agents/safe-data-access)         |

## Developer Resources

* [Learning Machines](/learning/overview)
* [Learning modes](/learning/learning-modes)
* [Decision Log store](/learning/stores/decision-log)
* [Learned knowledge cookbook](https://github.com/agno-agi/agno/tree/main/cookbook/08_learning/05_learned_knowledge)
