fastaiagent learn¶
Extract durable facts from past traces and re-inject them via PersistentFactBlock. Not to be confused with Memory(learn=llm), which learns during a run — see How memory works.
fastaiagent learn [--scope SCOPE] [--scope-id ID] [--agent NAME] [--window N]
[--max-traces N] [--max-facts N] [--model NAME] [--provider NAME]
[--dry-run] [--reprocess] [--allow-personal] [--attribute-all]
fastaiagent learn list [--scope SCOPE] [--scope-id ID] [--limit N]
[--show-superseded]
fastaiagent learn supersede OLD_ID NEW_ID
Default action — extract¶
Without a subcommand, fastaiagent learn mines the traces you point it at — newest first:
# my-agent's traces from the last 24h, filed as agent:my-agent facts.
fastaiagent learn --scope-id my-agent --agent my-agent
# Preview — no rows written, nothing recorded as mined.
fastaiagent learn --scope-id my-agent --agent my-agent --dry-run
# Wider window.
fastaiagent learn --scope-id my-agent --agent my-agent --window 168 # last week
Which traces it reads:
- only those that started within
--windowhours; - with
--agent, only traces in which that agent ran — at the root, or as a child span inside a swarm, chain or supervisor. Without it, every agent's traces in the window are read and every fact is filed under the one--scope-id; - never its own extraction calls (they run under a
learn.extractroot span); - not traces already mined for this scope and id — a re-run only reads new traces, and a trace that yielded nothing isn't billed again.
--reprocessmines them again. A trace whose extraction failed isn't recorded, so the next run retries it; - at most
--max-tracesof them.
The summary reports new facts separately from facts that were already known.
Flags¶
| Flag | Default | Notes |
|---|---|---|
--scope |
agent |
One of user | project | agent. |
--scope-id |
"" |
Identifier within scope. Required for user / project. |
--agent |
— | Only mine traces in which this agent ran. Required for user / project. |
--project-id |
"" |
The project partition the facts are stored under. It does not filter which traces are read. |
--window / --last-hours |
24 |
Only traces that started within this many hours. |
--max-traces |
100 |
Mine at most this many traces per run, newest first. |
--reprocess |
off | Mine traces again even if an earlier run already did for this scope and id. |
--max-facts |
10 |
Cap per trace. |
--model |
gpt-4o-mini |
Extractor LLM — cheap + fast recommended. |
--provider |
openai |
Any provider supported by LLMClient. |
--dry-run |
off | Show candidates without writing. |
--allow-personal |
off | Required for --scope user and --scope project. Default-off so PII extraction is always an explicit opt-in. |
--attribute-all |
off | Required for --scope user and --scope project: confirms every selected trace belongs to --scope-id (see Privacy). |
list — inspect what's stored¶
fastaiagent learn list --scope agent --scope-id my-agent
fastaiagent learn list --show-superseded # include audit history
Output is a Rich table with id, scope, scope_id, fact (cut to 120 characters), source (the first 12 characters of the source trace id), and status (active or superseded by N).
supersede — manual conflict resolution¶
Marks fact 12 as replaced by fact 34. The old row is preserved for audit; the new row becomes the active one for any consumer that filters on superseded_by IS NULL (which list_active and PersistentFactBlock do).
Pairing with PersistentFactBlock¶
import fastaiagent as fa
from fastaiagent.agent.memory_blocks import PersistentFactBlock
memory = fa.ComposableMemory(
primary=fa.AgentMemory(),
blocks=[PersistentFactBlock(scope="agent", scope_id="my-agent", max_facts=30)],
)
agent = fa.Agent(name="my-agent", system_prompt="…", llm=llm, memory=memory)
The block is read-only at runtime. New facts come from this CLI, from Memory(learn=llm) / FactExtractionBlock(persist=True) during runs, and from Memory.persist / MemoryStore.add in your own code.
Privacy¶
fastaiagent learn extracts only agent-scoped facts by default. --scope user and --scope project need four things:
--allow-personal, so PII extraction is never a surprise side effect;- a non-empty
--scope-id, since facts under an empty id can't be read back; --agent, so the run reads one agent's traces rather than everyone's;--attribute-all, because traces carry no user id: every trace the run reads is filed under that one--scope-id. Use it only when the selected traces all belong to that user or project.
The extraction prompt also instructs the model to skip names, emails, phone numbers, and addresses. This is best-effort, not a guarantee. Always review extracted facts before deploying to production.