# Learned Knowledge (/learning/stores/learned-knowledge)



The Learned Knowledge Store captures reusable insights, patterns, and best practices that apply across users and sessions. Semantic search lets agents find and apply relevant knowledge automatically.

| Aspect              | Value                                            |
| ------------------- | ------------------------------------------------ |
| **Scope**           | Configurable (global, user, or custom namespace) |
| **Persistence**     | Long-term                                        |
| **Default mode**    | Agentic                                          |
| **Supported modes** | Always, Agentic, Propose                         |
| **Requires**        | Knowledge base with vector database              |

## Setup [#setup]

```bash
pip install agno openai sqlalchemy "psycopg[binary]" pgvector
export OPENAI_API_KEY="your-api-key"
```

The examples use a local PostgreSQL database on port 5532. With Docker running, start it using:

<Steps>
    <Step title="Run PgVector">
      <CodeBlockTabs defaultValue="macOS / Linux">
        <CodeBlockTabsList>
          <CodeBlockTabsTrigger value="macOS / Linux">
            macOS / Linux
          </CodeBlockTabsTrigger>

          <CodeBlockTabsTrigger value="Windows">
            Windows
          </CodeBlockTabsTrigger>
        </CodeBlockTabsList>

        <CodeBlockTab value="macOS / Linux">
          ```bash
          docker run -d \
            -e POSTGRES_DB=ai \
            -e POSTGRES_USER=ai \
            -e POSTGRES_PASSWORD=ai \
            -e PGDATA=/var/lib/postgresql \
            -v pgvolume:/var/lib/postgresql \
            -p 5532:5432 \
            --name pgvector \
            agnohq/pgvector:18
          ```
        </CodeBlockTab>

        <CodeBlockTab value="Windows">
          ```powershell
          docker run -d `
            -e POSTGRES_DB=ai `
            -e POSTGRES_USER=ai `
            -e POSTGRES_PASSWORD=ai `
            -e PGDATA=/var/lib/postgresql `
            -v pgvolume:/var/lib/postgresql `
            -p 5532:5432 `
            --name pgvector `
            agnohq/pgvector:18
          ```
        </CodeBlockTab>
      </CodeBlockTabs>
    </Step>
</Steps>

Later configuration fragments reuse the imports and `db` from the first complete example.

## Prerequisites [#prerequisites]

Learned Knowledge requires a Knowledge base for semantic search:

```python
from agno.knowledge import Knowledge
from agno.knowledge.embedder.openai import OpenAIEmbedder
from agno.vectordb.pgvector import PgVector, SearchType

knowledge = Knowledge(
    vector_db=PgVector(
        db_url="postgresql+psycopg://ai:ai@localhost:5532/ai",
        table_name="learned_knowledge",
        search_type=SearchType.hybrid,
        embedder=OpenAIEmbedder(id="text-embedding-3-small"),
    ),
)
```

## Basic Usage [#basic-usage]

```python
from agno.agent import Agent
from agno.db.postgres import PostgresDb
from agno.learn import LearningMachine
from agno.models.openai import OpenAIResponses

db = PostgresDb(db_url="postgresql+psycopg://ai:ai@localhost:5532/ai")

agent = Agent(
    model=OpenAIResponses(id="gpt-5.2"),
    db=db,
    learning=LearningMachine(
        knowledge=knowledge,
        learned_knowledge=True,
    ),
)

# User 1 saves an insight
agent.print_response(
    "Save this: When comparing cloud providers, always check egress costs first - "
    "they can be 10x different between providers.",
    user_id="alice@example.com",
)

# User 2 benefits from the insight
agent.print_response(
    "I'm choosing between AWS and GCP for our data platform. What should I consider?",
    user_id="bob@example.com",
)
```

## Agentic Mode [#agentic-mode]

The agent receives tools to manage knowledge explicitly.

```python
from agno.learn import LearningMachine, LearningMode, LearnedKnowledgeConfig

agent = Agent(
    model=OpenAIResponses(id="gpt-5.2"),
    db=db,
    learning=LearningMachine(
        knowledge=knowledge,
        learned_knowledge=LearnedKnowledgeConfig(mode=LearningMode.AGENTIC),
    ),
)
```

Available tools: `search_learnings`, `save_learning`

The agent searches before answering questions and before saving (to avoid duplicates).

## Propose Mode [#propose-mode]

The agent proposes learnings for user confirmation before saving.

```python
from agno.learn import LearningMachine, LearningMode, LearnedKnowledgeConfig

agent = Agent(
    model=OpenAIResponses(id="gpt-5.2"),
    db=db,
    learning=LearningMachine(
        knowledge=knowledge,
        learned_knowledge=LearnedKnowledgeConfig(mode=LearningMode.PROPOSE),
    ),
)

agent.print_response(
    "That's a great insight about Docker networking. We should remember that.",
    user_id="alice@example.com",
)
# The agent proposes the learning and waits for user confirmation before saving
```

<Note>
  Propose mode is enforced through system prompt instructions, not application code. The `save_learning` tool stays available for the rest of the run, so the agent is expected to wait for a "yes" but isn't blocked from saving without one.
</Note>

## Always Mode [#always-mode]

Learnings are extracted concurrently with the main model call from its input snapshot.

```python
from agno.learn import LearningMachine, LearningMode, LearnedKnowledgeConfig

agent = Agent(
    model=OpenAIResponses(id="gpt-5.2"),
    db=db,
    learning=LearningMachine(
        knowledge=knowledge,
        learned_knowledge=LearnedKnowledgeConfig(mode=LearningMode.ALWAYS),
    ),
)
```

The tradeoff is an extra LLM call per interaction, and it may save low-value insights.

<Warning>
  In the current implementation, Always-mode duplicate lookup omits namespace and user filters. On a shared Knowledge instance, records from other scopes can therefore enter the extraction model's prompt. Use agentic capture for scoped runtime writes and recall, or give automatic extraction a physically separate Knowledge instance containing only the permitted corpus. A namespace setting alone does not correct this extraction lookup.
</Warning>

## Data Model [#data-model]

| Field        | Description                 |
| ------------ | --------------------------- |
| `title`      | Short, searchable title     |
| `learning`   | The actual insight          |
| `context`    | When/where this applies     |
| `tags`       | Categories for organization |
| `namespace`  | Sharing scope               |
| `user_id`    | Owner (if namespace="user") |
| `created_at` | When captured               |

## What to Save [#what-to-save]

| Good to save               | Don't save                |
| -------------------------- | ------------------------- |
| Non-obvious discoveries    | Raw facts or data         |
| Reusable patterns          | User-specific preferences |
| Domain-specific insights   | Common knowledge          |
| Problem-solving approaches | Conversation summaries    |
| Best practices             | Temporary information     |

**Good example:**

> "When comparing cloud providers, check current egress pricing for the expected traffic path, regions, and usage tiers before estimating total cost."

**Poor example:**

> "AWS has egress costs."

## Accessing Learned Knowledge [#accessing-learned-knowledge]

```python
lm = agent.learning_machine

# Search for relevant learnings
results = lm.learned_knowledge_store.search(query="cloud costs", namespace="global", limit=5)
for result in results:
    print(f"{result.title}: {result.learning}")

# Debug output
lm.learned_knowledge_store.print(query="cloud costs", namespace="global")
```

## Context Injection [#context-injection]

Relevant learnings are injected via semantic search:

```
<relevant_learnings>
Prior insights that may help with this task:

1. **Cloud egress cost variations**
   Always check egress costs first - they can be 10x different between providers.
   _Context: When selecting cloud providers for data-intensive workloads_
2. **API rate limiting strategies**
   Use token bucket algorithm for rate limiting - it handles bursts better than fixed windows.
   _Context: When designing APIs with high traffic_

Apply these naturally if relevant. Current context takes precedence.
</relevant_learnings>
```

## Namespaces [#namespaces]

Control knowledge sharing:

```python
from agno.learn import LearnedKnowledgeConfig

# Global: shared with all users (default)
learned_knowledge=LearnedKnowledgeConfig(namespace="global")

# User: private per user
learned_knowledge=LearnedKnowledgeConfig(namespace="user")

# Custom: team or domain-specific
learned_knowledge=LearnedKnowledgeConfig(namespace="engineering")
```

Runtime recall and agentic tools honor an explicit operation namespace, otherwise the store's configured namespace. A config at its `"global"` default can inherit a non-global `LearningMachine.namespace`.

Direct `search()` is different: omitting `namespace` searches without a namespace filter. For a private store, pass both explicitly:

```python
results = lm.learned_knowledge_store.search(
    query="cloud costs",
    namespace="user",
    user_id="alice@example.com",
    limit=5,
)
```

The Always-mode duplicate lookup limitation described above still applies when using private namespaces.

## Combining with Other Stores [#combining-with-other-stores]

```python
from agno.learn import LearningMachine

agent = Agent(
    model=OpenAIResponses(id="gpt-5.2"),
    db=db,
    learning=LearningMachine(
        knowledge=knowledge,
        user_profile=True,       # Who the user is
        user_memory=True,        # User's preferences
        learned_knowledge=True,  # Collective insights
    ),
)
```

You get personalized responses that draw on collective knowledge.
