Agentic.Memory.FactExtractor (agentic v0.2.2)

Copy Markdown

Fact extraction from tool results and LLM responses.

The core extraction functions (extract_from_tool_result/3, extract_from_response/2) use pure regex-based pattern matching — NO LLM calls, NO GenServer. These are designed to run synchronously after every tool call.

An optional LLM-assisted path (extract_with_llm/4) provides deeper extraction for complex turns, gated by qualifies_for_llm_extraction?/3 heuristics to limit cost.

Each fact is a map with:

  • entity — the subject (file path, tool name, concept)
  • relation — the predicate (mentions, produced_error, succeeded, decided, etc.)
  • value — the object (the path, error message, decision text, etc.)
  • confidence — 0.0 to 1.0
  • source_turn — which conversation turn produced this fact

Summary

Functions

Extract facts from an LLM response text.

Extract facts from a tool result.

Extract facts using an LLM call. Synchronous — wraps llm_chat directly.

Check if the current turn qualifies for LLM-assisted fact extraction.

Types

fact()

@type fact() :: %{
  entity: String.t(),
  relation: String.t(),
  value: String.t(),
  confidence: float(),
  source_turn: integer()
}

Functions

extract_from_response(text, turn)

@spec extract_from_response(String.t(), integer()) :: [fact()]

Extract facts from an LLM response text.

Looks for decisions, file paths, and error mentions.

extract_from_tool_result(tool_name, result, turn)

@spec extract_from_tool_result(String.t(), String.t(), integer()) :: [fact()]

Extract facts from a tool result.

Takes the tool name, result string, and current turn number.

extract_with_llm(response_text, tool_summaries, turn, llm_chat \\ nil)

@spec extract_with_llm(String.t(), list(), integer(), function() | nil) :: [fact()]

Extract facts using an LLM call. Synchronous — wraps llm_chat directly.

Accepts an optional llm_chat function as the 4th argument. If nil, returns []. The function should accept a params map and return {:ok, response} or {:error, reason}.

Returns a list of fact maps with optional :supersedes field.

qualifies_for_llm_extraction?(tool_names, response_text, turn)

@spec qualifies_for_llm_extraction?(list(), String.t(), integer()) :: boolean()

Check if the current turn qualifies for LLM-assisted fact extraction.

Heuristics:

  • 3+ tool calls in the turn
  • Response contains decision language
  • Agent used memory_write