This example demonstrates an AI agent with persistent memory that uses Feast as both a feature store and a context memory layer through the Model Context Protocol (MCP). This demo uses Milvus as the vector-capable online store, but Feast supports multiple vector backends -- including Milvus, Elasticsearch, Qdrant, PGVector, and FAISS -- swappable via configuration.
GitBook Assistant
Why Feast for Agents?
Agents need more than just access to data -- they need to remember what happened in prior interactions. Feast's online store is entity-keyed, low-latency, governed, and supports both reads and writes, making it a natural fit for agent context and memory.
Auto-checkpointed after each turn via write_to_online_store
GitBook Assistant
Governance
GitBook Assistant
RBAC, audit trails, and feature-level permissions
GitBook Assistant
TTL management
GitBook Assistant
Declarative expiration on feature views (memory auto-expires)
GitBook Assistant
Offline analysis
GitBook Assistant
Memory is queryable offline like any other feature
GitBook Assistant
Architecture
Tools (backed by Feast)
The agent has four tools. Feast is both the read path (context) and the write path (memory):
GitBook Assistant
Tool
Direction
What it does
When the LLM calls it
lookup_customer
GitBook Assistant
READ
GitBook Assistant
Fetches customer profile features (plan, spend, tickets)
GitBook Assistant
Questions about the customer's account
GitBook Assistant
search_knowledge_base
GitBook Assistant
READ
GitBook Assistant
Retrieves support articles from the vector store
GitBook Assistant
Questions needing product docs
GitBook Assistant
recall_memory
GitBook Assistant
READ
GitBook Assistant
Reads past interaction context (last topic, open issues, preferences)
GitBook Assistant
Start of every conversation
GitBook Assistant
Memory is auto-saved after each agent turn (not as an LLM tool call). This follows the same pattern used by production frameworks -- see Memory as Infrastructure below.
GitBook Assistant
Feast as Context Memory
The agent_memory feature view stores per-customer interaction state:
GitBook Assistant
This gives agents persistent, governed, entity-keyed memory that survives across sessions, is versioned, and lives under the same RBAC as every other feature -- unlike an ad-hoc Redis cache or an in-process dict.
GitBook Assistant
Memory as Infrastructure
Production agent frameworks treat memory as infrastructure, not an LLM decision. The framework auto-saves state after each step - the LLM never needs to "decide" to persist:
GitBook Assistant
Framework
Memory mechanism
How it works
LangGraph
GitBook Assistant
Checkpointers (MemorySaver, PostgresSaver)
GitBook Assistant
Every graph step is checkpointed automatically by thread_id
GitBook Assistant
CrewAI
GitBook Assistant
Built-in memory (memory=True)
GitBook Assistant
Short-term, long-term, and entity memory auto-persist after each task
GitBook Assistant
AutoGen
GitBook Assistant
Teachable agents
GitBook Assistant
Post-conversation hooks extract and store learnings in a vector DB
GitBook Assistant
OpenAI Agents SDK
GitBook Assistant
Application-level
GitBook Assistant
Serialize RunResult between turns; framework manages state
GitBook Assistant
This demo follows the same pattern: the agent's three read tools (recall_memory, lookup_customer, search_knowledge_base) are exposed to the LLM for reasoning, while memory persistence is handled by the framework after each turn via _auto_save_memory. This ensures consistent, reliable memory regardless of LLM behaviour - no risk of the LLM forgetting to save, double-saving, or writing inconsistent state.
GitBook Assistant
Feast is a natural fit for this checkpoint layer because it already provides:
GitBook Assistant
Entity-keyed storage: memory is keyed by customer ID (or any entity)
GitBook Assistant
TTL management: memory auto-expires via declarative feature view TTL
RBAC and audit trails: memory reads/writes are governed like any other feature
GitBook Assistant
Offline queryability: agent memory can be analysed in batch pipelines
GitBook Assistant
Prerequisites
Python 3.10+
GitBook Assistant
Feast with MCP and Milvus support
GitBook Assistant
OpenAI API key (for live tool-calling; demo mode works without it)
GitBook Assistant
Quickstart
One command
The script installs dependencies, generates sample data, starts the Feast server, runs the agent, and cleans up on exit.
GitBook Assistant
Step by step
1. Install dependencies
2. Generate sample data and apply the registry
This creates:
GitBook Assistant
3 customer profiles with attributes like plan tier, spend, and satisfaction score
GitBook Assistant
6 knowledge-base articles with 384-dimensional vector embeddings
GitBook Assistant
Empty agent memory scaffold (populated as the agent runs)
GitBook Assistant
3. Start the Feast MCP Feature Server
4. Run the agent
In a new terminal:
GitBook Assistant
To run with a real LLM, set the API key and (optionally) the base URL:
GitBook Assistant
Demo mode output
Without an API key, the agent simulates the decision-making process with memory:
GitBook Assistant
Scene 4 demonstrates memory continuity -- the agent recalls the SSO conversation from Scene 1 without the customer re-explaining.
GitBook Assistant
Live mode output (with API key)
With an API key, the LLM autonomously decides which tools to use:
GitBook Assistant
How It Works
Why a raw loop? This example builds the agent from scratch using the OpenAI tool-calling API and the MCP Python SDK to keep dependencies minimal and make every Feast call visible. All Feast interactions go through the MCP protocol -- the agent connects to Feast's MCP endpoint, discovers tools dynamically, and invokes them via session.call_tool(). In production, you would use a framework like LangChain/LangGraph, LlamaIndex, CrewAI, or AutoGen -- Feast's MCP endpoint lets any of them auto-discover the tools with zero custom wiring (see MCP Integration below).
GitBook Assistant
The Agent Loop (agent.py)
The LLM sees the tool definitions (JSON Schema) and decides:
GitBook Assistant
Which tools to call (can call zero, one, or multiple per round)
GitBook Assistant
What arguments to pass (e.g., which customer ID to look up)
GitBook Assistant
When to stop (once it has enough information to answer)
GitBook Assistant
All Feast calls go through MCP (session.call_tool()), not direct REST. Memory is saved automatically after each turn by the framework, not by the LLM. This mirrors how production frameworks handle persistence (see Memory as Infrastructure).
GitBook Assistant
Feature Definitions (feature_repo/features.py)
customer_profile: Structured data (name, plan, spend, tickets, satisfaction)
GitBook Assistant
knowledge_base: Support articles with 384-dim vector embeddings (Milvus in this demo; swappable to Elasticsearch, Qdrant, PGVector, or FAISS)
GitBook Assistant
agent_memory: Per-customer interaction history (last topic, resolution, preferences, open issues)
GitBook Assistant
MCP Integration
The Feast Feature Server exposes all endpoints as MCP tools at http://localhost:6566/mcp. Any MCP-compatible framework can connect:
GitBook Assistant
Building the same agent with a framework: The examples above show the Feast-specific part -- connecting to the MCP endpoint and getting the tools. Once you have the tools, building the agent follows each framework's standard patterns. The key difference from this demo's raw loop: frameworks handle the tool-calling loop, message threading, and (with LangGraph checkpointers or CrewAI memory=True) automatic state persistence natively. Feast's MCP endpoint means zero custom integration code -- the tools are discovered and callable immediately.
GitBook Assistant
Adapting to your use case: The demo's system prompt, tool wrappers (lookup_customer, recall_memory), and feature views are all specific to customer support. For your own agent, you define your feature views in Feast (e.g., product_catalog, order_history, fraud_signals), run feast apply, and start the server. The same three generic MCP tools -- get_online_features, retrieve_online_documents, and write_to_online_store -- serve any domain. With a framework like LangChain or LlamaIndex, you don't even need custom tool wrappers -- the LLM calls the generic Feast tools directly with your feature view names and entities.
GitBook Assistant
Production Deployment
For production, Feast fits into a layered platform architecture:
GitBook Assistant
This demo uses Milvus Lite (embedded). For production, swap to any supported vector-capable backend by updating feature_store.yaml:
GitBook Assistant
Milvus cluster: Deploy via the Milvus Operator and set host/port instead of path.
GitBook Assistant
Elasticsearch: Set online_store: type: elasticsearch with your cluster URL.
GitBook Assistant
Qdrant: Set online_store: type: qdrant with your Qdrant endpoint.
GitBook Assistant
PGVector: Set online_store: type: postgres with pgvector_enabled: true.
GitBook Assistant
FAISS: Set online_store: type: faiss for in-process vector search.
=================================================================
Scene 1: Enterprise customer (C1001) asks about SSO
Customer: C1001 | Query: "How do I set up SSO for my team?"
=================================================================
[Demo mode] Simulating agent reasoning
Round 1 | recall_memory(customer_id=C1001)
-> No prior interactions found
Round 1 | lookup_customer(customer_id=C1001)
-> Alice Johnson | enterprise plan | $24,500 spend | 1 open tickets
Round 1 | search_knowledge_base(query="How do I set up SSO for my team?...")
-> Best match: "Configuring single sign-on (SSO)"
Round 2 | Generating personalised response...
─────────────────────────────────────────────────────────────
Agent Response:
─────────────────────────────────────────────────────────────
Hi Alice!
Since you're on our Enterprise plan, SSO is available for your
team. Go to Settings > Security > SSO and enter your Identity
Provider metadata URL. We support SAML 2.0 and OIDC...
[Checkpoint] Memory saved: topic="SSO setup"
=================================================================
Scene 4: C1001 returns -- does the agent remember Scene 1?
Customer: C1001 | Query: "I'm back about my SSO question from earlier."
=================================================================
[Demo mode] Simulating agent reasoning
Round 1 | recall_memory(customer_id=C1001)
-> Previous topic: SSO setup
-> Open issue: none
-> Interaction count: 1
Round 1 | lookup_customer(customer_id=C1001)
-> Alice Johnson | enterprise plan | $24,500 spend | 1 open tickets
Round 2 | Generating personalised response...
─────────────────────────────────────────────────────────────
Agent Response:
─────────────────────────────────────────────────────────────
Welcome back, Alice! I can see from our records that we last
discussed "SSO setup". How can I help you today?
[Checkpoint] Memory saved: topic="SSO setup"
GitBook AssistantAskCopy
=================================================================
Scene 1: Enterprise customer (C1001) asks about SSO
Customer: C1001 | Query: "How do I set up SSO for my team?"
=================================================================
[Round 1] Tool call: recall_memory({'customer_id': 'C1001'})
[Round 1] Tool call: lookup_customer({'customer_id': 'C1001'})
[Round 1] Tool call: search_knowledge_base({'query': 'SSO setup'})
Agent finished after 2 round(s)
─────────────────────────────────────────────────────────────
Agent Response:
─────────────────────────────────────────────────────────────
Hi Alice! Since you're on our Enterprise plan, SSO is available
for your team. Go to Settings > Security > SSO and enter your
Identity Provider metadata URL. We support SAML 2.0 and OIDC...
[Checkpoint] Memory saved: topic="SSO setup"
GitBook AssistantAskCopy
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client
async with streamablehttp_client("http://localhost:6566/mcp") as (r, w, _):
async with ClientSession(r, w) as session:
await session.initialize()
tools = await session.list_tools() # discover Feast tools
for round in range(MAX_ROUNDS):
# 1. Send messages + read tools to LLM
response = call_llm(messages, tools=[...])
# 2. If LLM says "stop" -> return the answer
if response.finish_reason == "stop":
break
# 3. Execute tool calls via MCP
for tool_call in response.tool_calls:
result = await session.call_tool(name, args)
messages.append(tool_result(result))
# 4. Framework-style checkpoint: auto-save via MCP
await session.call_tool("write_to_online_store", {...})
GitBook AssistantAskCopy
# LangChain / LangGraph
from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.prebuilt import create_react_agent
async with MultiServerMCPClient(
{"feast": {"url": "http://localhost:6566/mcp", "transport": "streamable_http"}}
) as client:
tools = client.get_tools()
agent = create_react_agent(llm, tools)
result = await agent.ainvoke({"messages": "How do I set up SSO?"})
GitBook AssistantAskCopy
# LlamaIndex
from llama_index.tools.mcp import aget_tools_from_mcp_url
from llama_index.core.agent.function_calling import FunctionCallingAgent
from llama_index.llms.openai import OpenAI
tools = await aget_tools_from_mcp_url("http://localhost:6566/mcp")
agent = FunctionCallingAgent.from_tools(tools, llm=OpenAI(model="gpt-4o-mini"))
response = await agent.achat("How do I set up SSO?")