# Self-correcting agents (/use-cases/data-agents/self-correcting-agents)



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

```bash
uv pip install "agno[openai,pgvector,psycopg,sql]"
```

Set `OPENAI_API_KEY` in the environment before running the Python code. Replace the warehouse URLs with your own PostgreSQL connection strings and create the database roles, schemas, and grants described on this page first. The host `warehouse`, database `analytics`, and roles such as `readonly` and `dash_writer` are placeholders.

Examples using `PostgresDb` or `PgVector` also need a separate writable application database. The sample URL assumes a PostgreSQL service at `localhost:5532` with database/user/password `ai`; knowledge examples need the pgvector extension. See [PgVector setup](/knowledge/vector-stores/pgvector/overview). Keep this application's storage credentials separate from the restricted warehouse role.

```python
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 [#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 can call `search_learnings` before generating SQL.

In `AGENTIC` mode, retrieval occurs when the model calls `search_learnings`. The instruction in this example requests that search, but does not force a tool call.

## Choose how learning happens [#choose-how-learning-happens]

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

```python
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 model is instructed to ask before saving; the save tool itself has no confirmation gate | Conversational review of proposed learnings                                                           |

For an enforced approval boundary, route persistence through an application write protected by [human confirmation](/hitl/approval). `PROPOSE` instructions alone do not prevent `save_learning` from persisting a tool call.

`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 [#audit-what-it-learned]

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

```python
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 [#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 [#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)
