Skip to main content
Most “AI chatbots” are stateless wrappers around an LLM. They receive a message, generate a response, and forget everything. A true agent is fundamentally different: it perceives, thinks, acts, and remembers — building up knowledge over time that makes it better at its job. This guide walks you through the architecture behind intent-driven agents and builds a complete, production-ready chat agent using minns-sdk and Minns Memory Layer.

Part 1: How agents work

The agent loop

Every agent — from a simple customer service bot to an autonomous research assistant — follows the same core loop: A chatbot only does Perceive → Act. An agent does all four — and the Think and Remember phases are what give it intelligence over time.

Why stateless LLM wrappers fail

Consider a customer who contacts your bot three times:
  1. Monday: “I like Sci-Fi movies” → Bot responds, forgets.
  2. Wednesday: “What should I watch?” → Bot has no idea they like Sci-Fi.
  3. Friday: “I tried to book but it failed” → Bot has no context about the failure.
With an agent backed by Minns Memory Layer, every interaction is stored as an event. The agent forms memories, extracts claims (“User likes Sci-Fi”), and learns strategies (“When booking fails, offer alternative showtimes”). By Friday, the agent knows the user, remembers the failure, and has a strategy for recovery.

Part 2: The intent model

The most critical design decision in an agent is: how does the LLM’s free-form text output translate into structured actions? The naive approach is to prompt the LLM to return JSON. This breaks constantly — LLMs hallucinate brackets, forget commas, and wrap JSON in markdown fences. The intent model solves this cleanly.

The core idea

Instead of asking the LLM to be a JSON serializer, you separate its output into two distinct parts:
  1. The assistant response — natural language for the user (what the LLM is good at)
  2. The intent block — a structured action declaration in a fenced, parseable format
The LLM produces both in a single generation. A local parser (the sidecar) extracts the intent block without any additional network calls.
The sidecar parser splits this into:
  • assistantResponse: "Hey! I found 3 available seats..."
  • intent: { action: "show_options", movie: "Interstellar", options: [...] }

Why this works

LLM stays natural

The LLM writes prose — which it’s great at. It never has to produce valid JSON in isolation.

Parsing is deterministic

The intent block has rigid delimiters. Parsing is simple string splitting, not fragile JSON extraction.

No extra API calls

The sidecar runs locally. No second LLM call for “function calling” or “structured output.”

Fallback is graceful

If the LLM omits the intent block, you still have a valid assistant response. No crash.

The intent spec

An intent spec defines what actions your agent can take. Think of it as the agent’s “tool belt.” You declare the spec once, and the SDK generates the prompt instructions automatically.
The SDK converts this into a clear instruction block that gets appended to the LLM’s system prompt. The LLM learns to emit the ---INTENT--- block naturally.

The agent architecture

Here’s the full architecture of an intent-driven agent: The key insight: the LLM is just one component. It sits between the retrieval layer and the execution layer. Memory, strategies, and claims flow into the LLM as context, and structured intents flow out for execution.

Part 3: Building the agent

Let’s build this step by step. By the end, you’ll have a working chat agent with memory, knowledge extraction, and strategy-guided behavior.

Step 1: Project setup

agent.ts
This example uses OpenAI, but the intent model works with any LLM — Claude, Llama, Mistral, Gemini, or a local model. The sidecar parser doesn’t care which model produced the output.

Step 2: Define the intent spec

Define every action the agent can perform. Be specific — vague actions lead to vague intents.
agent.ts
Write action descriptions as if you’re training a new employee. Include when to use each action, not just what it does. This dramatically improves intent accuracy.

Step 3: Build the system prompt

The system prompt has three layers:
  1. Personality and role — who the agent is
  2. Sidecar instructions — how to format the intent block (auto-generated by the SDK)
  3. Dynamic context — memories, claims, and suggestions injected at runtime
agent.ts

Step 4: The retrieval layer

Before every LLM call, the agent gathers context from Minns Memory Layer. This is the Perceive phase.
agent.ts
The three retrievals run in parallel with Promise.all. This keeps latency low — you’re adding ~1 round-trip to Minns Memory Layer, not 3 sequential ones.

Step 5: The LLM call + sidecar parse

This is the Think phase. The LLM receives the enriched prompt and produces both a response and a structured intent.
agent.ts

Step 6: The execution layer

The Act phase. Each intent maps to a concrete function. This is where the agent does real work.
agent.ts

Step 7: The logging layer

The Remember phase. Every turn gets logged to Minns Memory Layer — the user message, the agent’s reasoning, the action, and the outcome. This is what powers memory formation, claim extraction, and strategy learning.
agent.ts
Use enqueue() for logging — it returns immediately and batches events in the background. This keeps the agent loop fast. Reserve send() for the final event where you need confirmation.

Step 8: The main agent loop

Now we wire everything together. This is the complete agent:
agent.ts
The finally block with client.flush() is essential. Without it, the last batch of events may be lost when the process exits.

Part 4: How the agent improves over time

The agent you just built doesn’t just respond — it learns. Here’s what happens behind the scenes after each conversation:

Claim extraction

When you log a Context event with enable_semantic: true (the default for the SDK), Minns Memory Layer extracts atomic facts: On the next session, searchClaims() retrieves these facts and injects them into the system prompt. The agent knows the user before they say anything.

Episode formation

Because every event carries the same goal("book_movie", ...), Minns Memory Layer groups them into an episode. When goalProgress hits 1.0, the episode completes and becomes a candidate for long-term memory. The next time a similar context appears (same goal, same user), getContextMemories() returns the past episode. The agent can say: “Last time you booked Interstellar row H — would you like the same?”

Strategy extraction

After several successful booking episodes, Minns Memory Layer detects a pattern:
Strategy: “standard_booking”
  1. Greet user, ask for movie
  2. Search available movies
  3. Check seat availability
  4. Confirm and book
Quality: 0.92 | Confidence: 0.88
This strategy appears in getSimilarStrategies() and gets injected into the system prompt as a “suggested next action.” The agent follows proven recipes instead of improvising every time.

Negative memory

When a booking fails — say the payment gateway is down — the failed episode is stored as a Negative memory. The next time the same context appears, the agent retrieves it and can proactively say: “I notice payments were slow earlier — let me check the status before we proceed.”

Part 5: Production considerations

Goal detection

In a real agent, the goal isn’t always “book_movie.” You need to detect the user’s intent and map it to a goal:
Always query memories by the correct goal. This prevents the agent from confusing “booking” history with “cancellation” history.

Conversation windowing

LLMs have limited context windows. For long conversations, trim the history:
The beauty of Minns Memory Layer is that trimmed messages aren’t lost — they’re already stored as events. Claims extracted from early turns persist in semantic memory even after the conversation window moves forward.

Error handling in the intent parser

The sidecar parser is resilient, but you should handle edge cases:

Multi-agent handoff

If your system has multiple specialized agents (booking, support, recommendations), use strategies to share knowledge:

Summary

The intent model gives your agent a clean separation between thinking (LLM) and doing (tools). Minns Memory Layer gives it the ability to remember and improve. Together, they turn a stateless chatbot into an agent that gets better with every conversation.

Quickstart

Get the SDK installed and running.

Sidecar reference

Deep dive into the sidecar parsing utilities.

Event builder

Full reference for the fluent event builder API.

Query selection

Learn which search to use for every retrieval pattern.