Integration

Memory for Haystack agents

Harny gives each person who uses your app a private memory the app's AI can read. Memory is dated, so it can say which value is current, what it replaced, and what was true on a given date. This page shows how to add Harny memory to a Haystack agent.

Jump to the code

What the framework does not keep

  • Which value is current. Harny memory is dated: a changed value with a newer timestamp becomes the current value, and the earlier value stays answerable by date.
  • When a fact happened. When you send a memory, you can set timestamp (ISO 8601 with zone) to say when it happened.
  • One person across sources. Harny keeps one private memory per person, and you read it with one recall call.

The pattern: memory as a tool

Expose memory as functions your agent can call, such as one to send a memory and one to recall. The model chooses which tool to call.

Your code binds the signed-in user to each tool call, so the model never chooses whose memory it reads. With an app key (fsa_), your server sends the user id in the X-Harny-User header. With a user key (fsk_), the key names its own user and needs no header. Call the Memory API from a server, never a browser.

import os
import requests
from haystack.tools import Tool

BASE = "https://api.harny.ai/v1/memory"

def make_memory_tools(user_id: str):
    headers = {
        "Authorization": f"Bearer {os.environ['HARNY_APP_KEY']}",
        "X-Harny-User": user_id,  # set by your application, never by the model
    }

    def recall_memory(question: str) -> str:
        r = requests.post(f"{BASE}/recall", headers=headers,
                          json={"query": question, "identity": user_id})
        return r.text

    def store_memory(text: str, happened_at: str) -> str:
        r = requests.post(f"{BASE}/ingest", headers=headers,
                          json={"content": text, "timestamp": happened_at})
        return r.text

    return [
        Tool(
            name="recall_memory",
            description="Look up what is known about this user that is relevant to a question.",
            parameters={"type": "object", "properties": {"question": {"type": "string"}}, "required": ["question"]},
            function=recall_memory,
        ),
        Tool(
            name="store_memory",
            description="Save a fact with the ISO time it happened.",
            parameters={
                "type": "object",
                "properties": {"text": {"type": "string"}, "happened_at": {"type": "string"}},
                "required": ["text", "happened_at"],
            },
            function=store_memory,
        ),
    ]

What recall returns

Memory with dated sources and source labels. Every result names the data point (source) behind it and the date it happened.

  • POST https://api.harny.ai/v1/memory/ingest takes id, content, label and timestamp.
  • POST https://api.harny.ai/v1/memory/recall takes query and identity, and returns results with sources.

Example: your agent asks “what is the Acme pilot budget?” and gets this back. Your code hands the model the content and the source label, so it can say who said it and when.

{
  "asOf": "2026-07-29T00:00:00Z",
  "results": [
    {
      "rank": 1,
      "occurredAt": "2026-07-28T16:00:00Z",
      "content": "Acme pilot budget: currently 40k.",
      "sources": [
        { "sourceId": "call-8821", "label": "Email from Nadia" }
      ]
    }
  ]
}

When to use which

  • Use Haystack's own state for the pipeline's working data: the current request, the components it runs, and the tool results of this turn.
  • Add Harny when the agent needs to remember a person across sessions, or needs to know which of two remembered values is current and what was true on a given date.

Frequently asked questions

Is a separate package needed?

The Memory API is called over HTTP with your app key, so the page should show the exact install step once it is confirmed.

Where does the user id come from?

Your app signs the person in and passes their id to the tool functions on your server. With an app key (fsa_), send it in the X-Harny-User header, and the model never sets it. A user key (fsk_) names its own user and needs no header.

Go on. Get Harny.

The first 500 monthly-active end users are free for good. Create an app key and make your first call in minutes.