Build

Any agent framework

Your agent framework can start oort mcp through its MCP client, like any other MCP server. Or call the oort CLI from your own code.

An agent framework with OortYour agent code starts oort mcp through the framework's MCP client, or runs the oort CLI directly. Either way, memories stay in ~/.oort on your machine.YOUR MACHINEYour agent codeany frameworkoortMCP server or CLIMemory~/.oort

Every example below needs the CLI on your PATH (npm i -g oortmem). Each one passes --project so the agent sees one project's memories, plus global ones. Recall works without keys. Saving new memories needs Oort Pro or your own keys.

Vercel AI SDK

Terminal
npm i ai @ai-sdk/mcp
TypeScript
import { createMCPClient } from '@ai-sdk/mcp';
import { Experimental_StdioMCPTransport } from '@ai-sdk/mcp/mcp-stdio';
import { generateText, isStepCount } from 'ai';

let client;

try {
  client = await createMCPClient({
    transport: new Experimental_StdioMCPTransport({
      command: 'oort',
      args: ['mcp', '--project', process.cwd()],
    }),
  });

  const tools = await client.tools();

  const { text } = await generateText({
    model: 'anthropic/claude-sonnet-5.5',
    tools,
    stopWhen: isStepCount(5),
    messages: [{ role: 'user', content: 'What did we decide about the deploy?' }],
  });

  console.log(text);
} finally {
  if (client) {
    await client.close();
  }
}

client.tools() turns Oort's MCP tools into AI SDK tools. stopWhen lets the model call recall and then answer. Close the client when you are done, so the oort mcp process ends.

LangGraph

Terminal
pip install langchain-mcp-adapters langchain langchain-openai
Python
import asyncio

from langchain.agents import create_agent
from langchain_mcp_adapters.client import MultiServerMCPClient


async def main():
    client = MultiServerMCPClient(
        {
            "oort": {
                "command": "oort",
                "args": ["mcp", "--project", "/path/to/repo"],
                "transport": "stdio",
            }
        }
    )
    tools = await client.get_tools()
    agent = create_agent("openai:gpt-4.1", tools)
    result = await agent.ainvoke({"messages": "What did we decide about the deploy?"})
    print(result["messages"][-1].content)


asyncio.run(main())

MultiServerMCPClient loads Oort's tools as LangChain tools, and create_agent runs them in a LangGraph agent. Without a long-lived session, the adapter starts a new oort mcp for each tool call.

OpenAI Agents SDK

Terminal
pip install openai-agents
Python
import asyncio

from agents import Agent, Runner
from agents.mcp import MCPServerStdio


async def main():
    async with MCPServerStdio(
        name="Oort",
        params={
            "command": "oort",
            "args": ["mcp", "--project", "/path/to/repo"],
        },
    ) as oort:
        agent = Agent(
            name="Assistant",
            instructions="Use Oort to recall what the user told you before.",
            mcp_servers=[oort],
        )
        result = await Runner.run(agent, "What did we decide about the deploy?")
        print(result.final_output)


asyncio.run(main())

MCPServerStdio starts oort mcp and stops it when the async with block ends.

Mastra

Terminal
npm i @mastra/core @mastra/mcp
TypeScript
import { Agent } from '@mastra/core/agent';
import { MCPClient } from '@mastra/mcp';

const mcp = new MCPClient({
  servers: {
    oort: {
      command: 'oort',
      args: ['mcp', '--project', process.cwd()],
    },
  },
});

const agent = new Agent({
  id: 'assistant',
  name: 'Assistant',
  instructions: 'Use Oort to recall what the user told you before.',
  model: 'openai/gpt-4.1',
  tools: await mcp.listTools(),
});

const response = await agent.generate('What did we decide about the deploy?');
console.log(response.text);

listTools() names each tool after its server, so the agent sees oort_recall, oort_remember and so on.

Your own code

No framework? Run the CLI. Recall before the model call, and observe after it.

Terminal
# memories for a question, as JSON
oort recall --json "how do we deploy?"
# run one finished turn through the write path
oort observe --user "We deploy from main with wrangler." --assistant "Noted."

Without --json, oort recall prints an <oort-memory> block you can put straight into a prompt. oort observe also reads one turn as JSON on stdin:

Terminal
echo '{"userText": "We deploy from main with wrangler.", "assistantText": "Noted."}' | oort observe

The same two calls from Node.js:

TypeScript
import { execFileSync } from 'node:child_process';

const repo = '/path/to/repo'; // the project comes from the folder

// Before the model call: recall what matters for this message.
const recalled = JSON.parse(
  execFileSync('oort', ['recall', '--json', userText], { cwd: repo, encoding: 'utf8' }),
);
const context = recalled.memories.map((m) => `- ${m.text}`).join('\n');

// After the reply: send the finished turn through the write path.
execFileSync('oort', ['observe'], {
  cwd: repo,
  input: JSON.stringify({ userText, assistantText }),
});
CommandPrints
oort recall --jsonmemories, each with id, text, type, tier and an explanation of its ranks.
oort observeThe outcome (added, reinforced, updated, superseded or skipped), the memory id and the decisions behind it.
oort observe --dry-runWhat the scrubber would redact. It saves nothing and calls no provider.