Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

MARK (Memory-Augmented Agent Recall Kit) Python SDK

mark-sdk is an agent memory runtime. It installs as mark-sdk from PyPI and imports as mark in Python.

MARK helps agents remember what they create, decide, observe, and learn across long-running workflows. It is built for more than chat history: stories, characters, images, videos, software projects, plans, design decisions, tool results, and multi-agent workflow state all need continuity.

The SDK combines memory storage, retrieval, context injection, observability, graph-scoped memory blocks, and tamper-evident provenance into a small developer API. Everything runs locally by default: no account, network, or API key is required.

from mark import Mark

with Mark.local(project_path=".") as mark:
    mark.memory.block("project").write(
        "The API framework is FastAPI.",
        importance=0.9,
    )

    context = mark.memory.retrieve("Which API framework does this project use?")
    print(context.as_text())

Why MARK

Most memory integrations start and end with store() and retrieve(). MARK is designed as an agent memory runtime: it participates in the agent loop, injects useful context before work, observes outcomes after work, and keeps memory inspectable as connected evidence rather than flat chunks.

Use MARK when an agent needs to:

  • remember creative continuity: characters, objects, shots, styles, plot points, and generated artifacts;
  • remember project decisions: architecture, conventions, constraints, implementation plans, and test results;
  • coordinate across agents: one agent plans, another implements, another tests, while all share durable local context;
  • preserve trust and provenance: group related memory into blocks, seal them, verify them later, and quarantine bad memory without breaking the rest of the agent;
  • adopt memory incrementally: add middleware or tools to an existing agent rather than rebuilding the application around a database.

MARK is not a managed memory database. The open SDK is the Apache-2.0-licensed runtime and integration layer.

Install

MARK supports Python 3.10 and newer.

pip install mark-sdk

Optional framework adapters are bundled under mark.adapters and installed through extras:

pip install "mark-sdk[langchain]"   # LangChain tools + agent middleware
pip install "mark-sdk[mcp]"        # MCP server over MARK memory
pip install "mark-sdk[adapters]"   # both of the above
pip install "mark-sdk[middleware]" # all local middleware batteries

Specific middleware install targets are also available, for example mark-sdk[middleware-governance], mark-sdk[middleware-trust-bus], mark-sdk[middleware-sandbox], and mark-sdk[middleware-media-continuity]. Most middleware batteries are pure Python today, so the extras mainly provide a stable install contract as dependency-bearing middleware grows.

Verify the installed package:

python -c "from mark import Mark; print(Mark.local('.').memory.list_blocks())"

Quickstart

1. Store and recall project memory

from mark import Mark

with Mark.local(".") as mark:
    mark.memory.block("architecture").write(
        "Authentication uses FastAPI dependencies and JWT.",
        importance=0.8,
    )

    result = mark.memory.retrieve("How is authentication implemented?")
    print(result.as_text())

2. Run the same agent with memory

import asyncio

from mark import Mark

def coding_agent(prompt: str) -> str:
    if "FastAPI" in prompt:
        return "Use FastAPI dependency injection for this endpoint."
    return "I need more project context."

with Mark.local(".") as mark:
    mark.memory.block("project").write("This backend uses FastAPI.")
    agent = mark.wrap_agent(coding_agent, blocks=["project"])

    result = asyncio.run(agent.run("Add a health-check endpoint."))
    print(result.output)

3. Track continuity across creative sessions

from mark import Mark

with Mark.local(".") as mark:
    memory = mark.runtime.memory("video-agent")

    memory.observe(
        "Elena enters the North Warehouse wearing the red scarf.",
        session_id="season-01/episode-01/scene-04",
        memory_type="scene",
    )

    scene_context = memory.retrieve_sync(
        "What must stay consistent for Elena?",
        session_prefix="season-01/",
    )
    print(scene_context.as_context())

4. Group creations and decisions into provenance blocks

Memory blocks bundle related fragments, nodes, and edges into one unit per topic, session, or world-bible scope. Blocks link to each other forward and backward, can be sealed into a tamper-evident hash chain, and can be quarantined — isolating bad memory without affecting the rest of the agent.

from mark import Mark

with Mark.local(".") as mark:
    memory = mark.runtime.memory("video-agent")
    graph  = memory.blocks()
    chain  = memory.chain()

    shot = graph.create_block("ep01-scene04", session_id="season-01/episode-01")
    graph.add_fragment(shot.id, memory.store_sync("Elena hides the key in the rafters."))

    # Retrieval scoped to one block
    result = memory.retrieve_sync("Where is the key?", block_id=shot.id)

    # Seal the block into the agent's provenance chain
    sealed = chain.seal(shot.id)
    print(sealed.content_hash)

    # Verify integrity later — pinpoints any corrupted member
    print(chain.verify(shot.id).valid)
    print(chain.verify_chain().valid)

    # Isolate a bad block without touching anything else
    chain.quarantine(shot.id)

5. Add memory to a LangChain agent as middleware

MarkAgentMiddleware turns MARK into a transparent context-window manager for any LangChain v1 agent: it watches the LangChain message history, retrieves only relevant memory before each model call, injects a compact memory block, and archives useful AI/tool evidence in the background. The LLM remains the reasoning machine; MARK supplies durable working memory.

from langchain.agents import create_agent

from mark import Mark
from mark.adapters.backend import LocalMarkBackend
from mark.adapters.langchain.middleware import MarkAgentMiddleware

with Mark.local(".") as mark:
    middleware = MarkAgentMiddleware(
        backend=LocalMarkBackend(mark, default_agent_id="coder"),
        agent_id="coder",
        max_context_chars=1400,     # context budget injected per model call
        write_outcomes=True,        # archive AI reasoning steps
        observe_tool_results=True,  # archive tool outputs as they happen
    )

    agent = create_agent(model, tools, middleware=[middleware])
    result = agent.invoke({"messages": [("user", "Fix the failing build.")]})

Prefer explicit control? create_mark_tools exposes memory as ordinary LangChain tools the model calls itself. The tools support both sync invoke() and async ainvoke() paths, including notebook environments with an already running event loop:

from mark.adapters.langchain import create_mark_tools

tools = create_mark_tools(
    LocalMarkBackend(mark, default_agent_id="coder"),
    default_agent_id="coder",
)
agent = create_agent(model, [*tools, *my_other_tools])

Use one surface by default: middleware for automatic context loading, or tools when the model should deliberately write canonical facts. Combining both is an advanced mode for targeted recall/write operations; keep injected context small so MARK does not duplicate information already loaded by the middleware.

And mark.adapters.mcp serves the same memory to any MCP-compatible client:

from mark.adapters.backend import LocalMarkBackend
from mark.adapters.mcp import create_mark_mcp_server

server = create_mark_mcp_server(LocalMarkBackend(mark))
server.run()  # stdio MCP server

The full middleware walkthrough — the same agent run with and without MARK, side by side — lives in the tutorial notebook under examples/.

6. Keep canonical creative facts in a world bible

from mark import Mark

with Mark.local(".") as mark:
    mark.world_bible.remember(
        "Elena is left-handed and always wears the red scarf in episode 01.",
        tags=["character:elena", "wardrobe"],
    )

    facts = mark.world_bible.check("Elena wardrobe and physical traits")
    for fact in facts:
        print(fact.content)

Comparative Samples

MARK examples are written as A/B comparisons: the same task runs once with ordinary short-term context and once with MARK-backed recall.

Scenario Without MARK With MARK What to inspect
Coding agent The agent answers from the current prompt only. Project conventions must be repeated. MARK recalls stored conventions before the model reasons. examples/02_agent_ab_live.py and examples/getting_started_with_mark.ipynb
LangChain agent Message history is whatever LangChain keeps in the active loop. MarkAgentMiddleware retrieves compact memory before model calls and observes useful tool/model evidence. README section 5 and the tutorial notebook
Creative continuity A generator without MARK only sees its prompt and short-term carryover. A MARK-aware agent recalls canonical identity/world facts and writes continuity observations between steps. MarkAgent, sessions, and world_bible

Generated media demo outputs and heavyweight provider clients are not included in mark-sdk.

Features

  • Agent-loop integration: wrap simple callables, attach LangChain middleware, expose MARK as tools, or serve memory over MCP.
  • Pluggable middleware: compose framework-neutral middleware for recall defaults, observation metadata, compression, query expansion, gap healing, lifecycle maintenance, observability, and sync envelope preparation.
  • Structured memory: fragments, sessions, graph nodes, graph edges, world-bible facts, and graph-scoped blocks.
  • Retrieval pipeline: local vector retrieval with graph expansion, scoring, gap reporting, optional query expansion, and optional contextual compression.
  • Creative continuity: session prefixes, tags, scopes, world-bible facts, and blocks make it natural to track characters, objects, locations, shots, styles, and generated artifacts.
  • Workflow memory: store plans, conventions, decisions, tool outputs, test results, and implementation state for coding or autonomous agents.
  • Provenance and integrity: SHA-256 block sealing, whole-chain verification, pinpointed corruption reports, and quarantine isolation.
  • Memory lifecycle: working memory with TTL expiry, consolidation, deduplication, pruning, reinforcement, and local governance gates.
  • Multi-agent sharing: trust-aware local bus for publisher trust, subscriptions, snapshots, and trust-filtered retrieval.
  • Local observability: JSONL traces, replay support, session activity logs, and middleware observation of reasoning/tool outcomes.

Everything in this package runs locally under the Apache-2.0 license.

MARK Cloud — coming soon

Watch out for MARK Cloud updates.

Examples

See examples/ for runnable developer usage tests and walkthroughs:

python examples/run_live_examples.py

The live examples cover:

  • local project memory storage and retrieval,
  • A/B agent usage with and without MARK context injection,
  • session-aware observe() continuity retrieval,
  • redacted sync envelope preparation.

The notebook in examples/ provides a longer step-by-step walkthrough for memory, retrieval, sessions, middleware, tools, MCP exposure, memory inspection, and provenance sealing.

Planned proof-oriented examples:

  • examples/multi-agent-coding/: demonstrate planner, implementer, and tester agents sharing decisions and workflow state through MARK.

Development

python examples/run_live_examples.py
uv run --extra dev pytest
uv build

Middleware

Core middleware lives under mark.middlewares and wraps existing public runtime operations. It is framework-neutral, so LangChain, MCP, and future adapters can share the same behavior instead of reimplementing recall, observation, compression, tracing, and sync logic.

from mark import Mark, ObserveMiddleware, ObservabilityMiddleware, RecallMiddleware

with Mark.local(
    ".",
    middleware=[
        RecallMiddleware(compress=True, expand=True),
        ObserveMiddleware(source="agent", tags=["workflow"]),
        ObservabilityMiddleware(),
    ],
) as mark:
    memory = mark.runtime.memory("coder")
    memory.observe("Use FastAPI dependency injection for routes.")
    result = memory.retrieve_sync("How should routes be implemented?")

Middleware is local and Apache-2.0-safe. Optional integrations can be attached through explicit hooks or caller-supplied clients.

Middleware batteries are opt-in. Without a middleware instance in the runtime, MARK stores and retrieves through the core memory primitives only; governance, trust-bus publication, sandbox execution, media continuity defaults, sync envelopes, compression, expansion, and automatic observation structuring are not activated.

Available local middleware includes recall, observe/writeback, compression, query expansion, governance, lifecycle, observability, sync, trust bus, sandbox, gap healing, and media continuity wrappers. Each middleware lives in its own package under mark.middlewares.

Contributing & support

  • Found a bug? Have an idea? Open an issue — the templates take two minutes, and "this surprised me" reports are welcome too.
  • Want to contribute? Start with CONTRIBUTING.md and the good first issue label. Draft PRs and questions are encouraged.
  • Using MARK in a project? Tell us in Discussions — real workloads drive the roadmap.
  • Security issues: see SECURITY.md — please report privately.

License

Apache-2.0 — see LICENSE.

Release files for mark-sdk 0.2.0a6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mark-sdk 0.2.0a6
File Size Uploaded
mark_sdk-0.2.0a6.tar.gz 408.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mark-sdk 0.2.0a6
File Interpreter ABI Platform
mark_sdk-0.2.0a6-py3-none-any.whl Python 3 none any Details

Total release size: 626.7 kB

Release files / mark_sdk-0.2.0a6.tar.gz

Download URL mark_sdk-0.2.0a6.tar.gz
Size 408.8 kB
Tags Source
SHA-256 checksum
How to use checksums
0164ffa805eeb0df0b7be6292613faa64f4e8dee7e5c475d9843f50db7fcad44
BLAKE2b-256 checksum
How to use checksums
ea465283417cc41ef4c4da01bf4b52da3d1050bba7bd2209aaf1ad1d20843a29
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / mark_sdk-0.2.0a6-py3-none-any.whl

Download URL mark_sdk-0.2.0a6-py3-none-any.whl
Size 217.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
94d83f0fdf89b639604792b6e8a43d083f5bd5d05a1fd6da4488df4a6ea4e525
BLAKE2b-256 checksum
How to use checksums
845c9ec1a28a50aa5a6d18a3eb9f10004225b4439d84cb1be876e9fbdc747a6f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.2.0a6 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page