Korely

n8n

n8n is a workflow automation platform with an AI Agent node. The agent can act, but it has no memory across executions: every workflow run starts from zero. Korely adds that memory. Attach HTTP Request nodes to your AI Agent workflow and point them at https://api.korely.ai/v1 with your API key (kor_live_...). The agent saves what matters at the end of a conversation and finds it again on the next run, the next day, or from a different workflow.

This guide uses the n8n HTTP Request node. It is built in, it works on n8n Cloud and on self-hosted n8n, and it sends JSON over HTTPS, which is what the Korely REST API expects. On a self-hosted n8n you can also install the Korely community node, described next.

The Korely community node (self-hosted n8n)

In a self-hosted n8n, open Settings, then Community Nodes, then Install, and enter n8n-nodes-korely. Without the panel, run cd ~/.n8n/nodes && npm install n8n-nodes-korely and restart n8n. The package is on npm.

The node covers Memory (Add, Search), Context (Get) and Fact (List, with As Of; Write; Close; Correct). Its credential asks for the address next to the key, and Test calls the address with the key, so a key pointed at the wrong server fails the test instead of the first run. A kor_live_ key pointed at your own install is told that keys of the hosted service begin with kor_live_ and do not work there.

n8n Cloud installs only verified community nodes, and this one is not verified yet (n8n's public listing of verified nodes had no entry for n8n-nodes-korely on 1 November 2026). On n8n Cloud, follow the HTTP Request steps below. We checked the node's operations and its credential in the published package (version 0.1.0); we did not run it inside n8n.

What you get

  • Memory across executions. Each n8n execution starts empty. With Korely attached, the agent saves decisions, summaries and facts with POST /v1/memories, and any later run can recall them with GET /v1/context, which returns a context block of the facts that are true now plus the best-matching memories.
  • Memory across workflows. The memory store is shared. A chat workflow saves a memory; a scheduled digest workflow reads it; the Korely dashboard shows it to you so you can inspect what agents have stored.
  • The whole REST API. Store memories, search them by meaning, get a context block, read facts, and manage agents and end users, all with ordinary HTTP calls from n8n nodes.

Prerequisites

You need a Korely API key (kor_live_...). Sign up at korely.ai. A Hobby account is free and is enough for this guide.

Step 1: store the credential

In n8n, create a Header Auth credential (or use a generic HTTP credential) with:

Name: Authorization
Value: Bearer kor_live_YOUR_KEY

You will reference this credential in every HTTP Request node that calls Korely, keeping the key out of individual nodes.

Step 2: build the workflow

The smallest memory-enabled agent uses four nodes:

Chat Trigger ──▶ Recall node ──▶ AI Agent ──▶ Save node ──▶ (reply)
│
Chat Model: your model
  1. Add a Chat Trigger node.
  2. Add an HTTP Request node called Recall. Point it at GET /v1/context. It returns one block with the facts that are true now plus the relevant memories, ready to drop into a prompt. user_id is the end user, and token_budget is the size limit of the block:
    Method: GET
    URL: https://api.korely.ai/v1/context
    Authentication: Header Auth → select your Korely credential
    Query params: query = {{ $json.chatInput }}
    user_id = {{ $json.sessionId }}
    token_budget = 800
  3. Add an AI Agent node. In its system message, inject the pre-formatted context block from the previous node:
    You have persistent memory. Here is what is known about the user:
    {{ $('Recall').item.json.context }}
    Use this context before answering. When the conversation produces a
    decision or durable fact, the workflow will save it automatically.
  4. Add a second HTTP Request node called Save, wired after the AI Agent:
    Method: POST
    URL: https://api.korely.ai/v1/memories
    Authentication: Header Auth → select your Korely credential
    Send Body: on
    Body Content Type: JSON
    Specify Body: Using Fields Below
    Body fields: content = {{ $('AI Agent').item.json.output }}
    user_id = {{ $('Chat Trigger').item.json.sessionId }}
    agent_id = n8n-chat

    n8n builds the JSON from the fields, so a reply with quotes or line breaks still sends a valid body. If you prefer Using JSON, make the whole body one expression that returns an object:

    {{ JSON.stringify({
    content: $('AI Agent').item.json.output,
    user_id: $('Chat Trigger').item.json.sessionId,
    agent_id: "n8n-chat"
    }) }}

    Never paste an expression inside a quoted JSON string ("content": "{{ ... }}"): the first quote or newline in the text breaks the JSON, and the call returns 422.

Step 3: smoke-test the connection

Verify the credential and endpoint are wired correctly before connecting a full agent. In a standalone HTTP Request node:

Terminal window
# from your terminal, the same call the node makes
curl -X POST https://api.korely.ai/v1/memories/search \
-H "Authorization: Bearer kor_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "test", "limit": 3}'

A 200 response with a results array confirms the key works and the endpoint is reachable. Then trigger the workflow from the Chat Trigger panel and check that the Save node returns a memory id.

Make the agent use memory on its own

The pattern above is fixed: the workflow always recalls and always saves. You can instead let the agent signal when something is worth saving. Add this to the agent's system message:

You have persistent memory through Korely.
- Prior context retrieved from memory is in your system prompt.
- When a conversation produces a decision, a summary, or a durable
fact, say [SAVE] at the end of your reply so the workflow persists it.
- Never ask permission to search or save. Just do it.

In n8n, add an IF node after the AI Agent that checks whether the output contains [SAVE], and route only those branches to the Save HTTP Request node.

Example: save in one run, recall in the next

Two separate executions of the same workflow. In the first, the Save node stores the memory. The next day the same chat user comes back and the Recall node finds it. Nothing passes between the runs except Korely. Recall only finds what was saved under the same user_id, so the session id you use for it has to identify the same person across conversations. The output below is an example, and your facts will differ.

n8n ai agent chat trigger
# Execution 1, Tuesday

You › We picked the Berlin venue for the team offsite. October
14 to 16, budget 6,000 EUR, Dana owns the agenda.

→ Save node POST /v1/memories
    body: {
      "content":  "Offsite decision: Berlin, Oct 14-16. Budget: 6,000
                   EUR. Agenda owner: Dana.",
      "user_id":  "session-abc123",
      "agent_id": "n8n-chat"
    }

← {"id": "mem_7c3e91a2...", "content": "Offsite decision: ..."}

Agent › Saved the offsite decision: Berlin, October 14-16,
6,000 EUR budget, Dana on the agenda. Anything else to capture?

# Execution 2, Wednesday, same chat user

You › Where did we land on the offsite?

→ Recall node GET /v1/context
    params: query=offsite venue decision  user_id=session-abc123  token_budget=800

← {"context": "_The facts below are a compact profile of the user;
      [...]_\n\n## Known facts\n- offsite has_agenda_owner Dana (since
      2026-06-16) [planned, not done]\n- offsite has_budget 6000 EUR
      (since 2026-06-16) [planned, not done]\n- offsite takes_place_in
      Berlin (since 2026-06-16) [planned, not done]\n\n## Relevant
      memories\n_A time in square brackets [...]_\n- [2026-06-16]
      Offsite decision: Berlin, Oct 14-16. Budget: 6,000 EUR. Agenda
      owner: Dana.",
   "sources": ["fct_e18a...", "fct_7380...", "fct_3e88...",
   "mem_7c3e91a2..."], "degraded": false, "degraded_parts": [], ...}

Agent › You decided on Berlin, October 14 to 16, with a 6,000
EUR budget. Dana owns the agenda. Want me to create a task to
book the venue?

/v1/context assembles its block from stored facts and memories. Facts that a newer one replaced are closed and do not appear. No language model runs on Korely's side when you read; your agent's chat model does the reasoning. Reads are cheap for us, so every plan allows at least 100 times more queries than writes per month (see the pricing page). A fact can take about ten seconds to appear after the write (extraction), so a second run seconds after the first may not see it yet.

When you want raw search hits

GET /v1/context suits most agents: one block to drop into a prompt. When you want individual scored memories to rank, filter or show yourself, call POST /v1/memories/search. It compares meaning and returns a results array, each item a { id, score, snippet, user_id, agent_id, metadata } object:

Terminal window
curl -X POST https://api.korely.ai/v1/memories/search \
-H "Authorization: Bearer kor_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "offsite", "user_id": "USER", "limit": 5}'

In n8n, take the snippet field before joining the hits into a prompt, because the items are objects, not strings: {{ $('Search').item.json.results.map(r => r.snippet).join('\n') }}.

Beyond chat

Nothing here needs a chat. Replace the Chat Trigger with any other trigger and the same HTTP Request nodes work:

  • Schedule Trigger: a nightly agent calls GET /v1/memories on a user and saves a digest summary back with POST /v1/memories.
  • Webhook or email trigger: before drafting a reply, the agent searches past context for the sender's name with POST /v1/memories/search.
  • Form trigger: intake forms become structured memories keyed by user_id, retrievable in any later workflow.

Troubleshooting

SymptomFix
HTTP 401 Unauthorized Body has "code": "invalid_key" and a message that says why: send it in the header Authorization: Bearer kor_live_... when the header is missing, a key of this install is kor_live_ followed by 43 characters when the value is malformed (for example wrapped in quotes or mistyped), and no live key matches it (unknown, revoked or expired) when the key is unknown, revoked or expired. Branch on code, not on the words. Check the Authorization header is exactly Bearer kor_live_YOUR_KEY with no extra spaces or quotes. Verify the credential is selected in the HTTP Request node.
HTTP 429 Too Many Requests The body tells you which limit you hit: "code": "quota_exceeded", with limit, used and resets_at in the body, means you have spent your monthly writes or queries (the message says which; 10% grace included). There is no Retry-After on a quota 429, so retrying in the same month will not help: stop the workflow until resets_at, top up the month's writes on a paid plan, or upgrade. A burst rate-limit 429 does carry a Retry-After header (integer seconds), add a Wait node for that many seconds before retrying. "code": "agent_cap_exceeded", with limit and used, means a new agent_id (such as n8n-chat) is past your plan's named agents (2 on Hobby): reuse an existing agent_id, leave it out, delete one with DELETE /v1/agents/{agent_id}, or upgrade. Hobby allows 25,000 queries and 250 writes per month.
Search returns empty results on first run No memories exist yet for that user_id. The first run saves; the second run recalls. Check the Save node executed successfully and returned a memory id.
Agent answers without using retrieved context Make sure the Recall node output is interpolated into the AI Agent's system message, not just passed as user input. The agent ignores context it cannot see in the prompt.
HTTP 422 Unprocessable Entity The request body is missing a required field. Check that content is present for writes, and query for searches. The response body names the field: {"code":"invalid_request","message":"content: Field required"}.

For the full REST endpoint reference, see the API reference. For how facts, supersession and time work, see temporal facts.

Something not working? Email [email protected] with your n8n version (Cloud or self-hosted) and a screenshot of the HTTP Request node settings. We read every message.