Skip to main content

Aura — aura-context-engine

A framework-agnostic context layer for LLM agents.

Retain every turn durably. Transmit per turn only what the current question needs — under an explicit token budget, with no LLM call on the read path.

Drop it into LangGraph, Agno, Google ADK, or a raw model loop. The engine owns the session; the orchestrator stays an orchestrator.

CI License: MIT Python 3.10+

Why this exists

Long agent transcripts waste three things at once:

  • Latency — prefill grows with every unused token
  • Cost — you pay for tokens the model does not need
  • Attention — models lose the middle of a long prompt (Lost in the Middle)

aura-context-engine keeps the full transcript in storage and assembles a budgeted prompt: pinned facts, the last turn, query-relevant recall, and (for teams) a distilled handoff — never the other agent's raw history.

Install

Python 3.10+.

pip install aura-context-engine

Until the first PyPI release, install from GitHub:

pip install "aura-context-engine @ git+https://github.com/hypen-code/aura.git"

From a local clone (editable):

git clone https://github.com/hypen-code/aura.git
cd aura
python3 -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate
pip install -e .

Optional extras

The core has zero required dependencies. Add only what you use.

Extra Install What it unlocks
(none) pip install aura-context-engine Assembly, SQLite/memory, BM25 recall, heuristic facts
embed pip install "aura-context-engine[embed]" Local fastembed semantic recall
extract pip install "aura-context-engine[extract]" Async LLM fact extraction via LiteLLM
langgraph pip install "aura-context-engine[langgraph]" LangGraphContextAdapter / team adapter
agno pip install "aura-context-engine[agno]" AgnoContextAdapter / team adapter
adk pip install "aura-context-engine[adk]" GoogleADKContextAdapter / team adapter
all pip install "aura-context-engine[all]" Everything above
pip install "aura-context-engine[embed,extract,langgraph]"

30-second usage

from context_engine import ContextEngine, ContextPolicy, PolicyMode

engine = ContextEngine()
session = engine.new_session()

engine.record_exchange(
    session,
    "I live in Oslo and I have two cats, Miso and Nori.",
    "Noted.",
)
engine.record_exchange(session, "I just moved to Berlin.", "Got it.")

policy = ContextPolicy(
    mode=PolicyMode.PRIORITY_SELECTIVE,
    recency_turns=1,
    top_k=4,
    token_budget=2048,
)

messages = engine.build_context(
    session,
    "Where do I live now, and what are my cats called?",
    policy=policy,
    system_prompt="Answer from the conversation only.",
)
# messages is a list of {role, content} dicts — pass it to any LLM API

Run the same flow from the repo:

python examples/quickstart.py

Add it to an orchestrator

The contract is two calls:

  1. Write — record_turn / record_exchange after a completed turn
  2. Read — build_context (or an adapter hook) before the next model call

Any framework (no adapter)

from context_engine import ContextEngine, ContextPolicy, PolicyMode

engine = ContextEngine()
session = engine.new_session()
policy = ContextPolicy(mode=PolicyMode.PRIORITY_SELECTIVE, token_budget=2048)

def reply(question: str, call_model) -> str:
    prompt = engine.build_context(session, question, policy=policy)
    answer = call_model(prompt)
    engine.record_exchange(session, question, answer)
    return answer

LangGraph

from langgraph.prebuilt import create_react_agent
from context_engine import ContextEngine, ContextPolicy, PolicyMode
from context_engine.adapters import LangGraphContextAdapter

engine = ContextEngine()
adapter = LangGraphContextAdapter(
    engine,
    policy=ContextPolicy(mode=PolicyMode.PRIORITY_SELECTIVE, token_budget=2048),
)
agent = create_react_agent(model=llm, tools=tools, pre_model_hook=adapter.pre_model_hook)

The hook replaces the model input with the assembled context and passes the live tool-call tail through untouched.

Agno

from agno.agent import Agent
from context_engine import ContextEngine
from context_engine.adapters import AgnoContextAdapter

engine = ContextEngine()
adapter = AgnoContextAdapter(engine)
agent = Agent(model=model, add_history_to_context=False)

prompt = adapter.messages_for(question)
response = agent.run(input=adapter.to_agno(prompt))
adapter.record_exchange(question, response.content)

Google ADK

from context_engine import ContextEngine
from context_engine.adapters import GoogleADKContextAdapter

engine = ContextEngine()
adapter = GoogleADKContextAdapter(engine, app_name="my-app")
session = await adapter.prepare_session(runner)
async for event in adapter.run(runner, session, question, agent_name="assistant"):
    ...

Multi-agent teams

Each agent gets its own scoped session. Cross-agent state moves as a handoff packet (short summary + identifier slots), not a shared transcript.

from context_engine import ContextEngine, TeamContext
from context_engine.adapters import LangGraphTeamAdapter

team = TeamContext(ContextEngine(), "order-1")
adapter = LangGraphTeamAdapter(team)

researcher = create_react_agent(
    model, tools, pre_model_hook=adapter.node_hook("researcher")
)
writer = create_react_agent(
    model, tools, pre_model_hook=adapter.node_hook("writer")
)

adapter.record_exchange("researcher", question, findings)
adapter.record_handoff("researcher", "writer", findings)

Same pattern: AgnoTeamAdapter, ADKTeamAdapter.

How assembly works

P1  system prompt + session facts + current question     never evicted
P2  most recent turn(s)                                  last
P3  handoffs / last tool response                        just before the question
P4  top-k query-relevant older turns                     recalled
P5  everything else                                      dropped first

Eviction under token_budget: P5 → shrink P4 → surplus P3 → shrink P2. A single remaining P3 block is never dropped (withholding a handoff is worse than a slightly over-budget prompt).

Write path is async: the turn is stored immediately; fact extraction and embeddings run on a background thread. The newest turn is already in P2, so the next read does not wait.

On any engine error the read path falls back to full-history replay.

Persistence

from context_engine import ContextEngine, SQLiteStorage

engine = ContextEngine(storage=SQLiteStorage("aura.db"))

Default is in-memory. SQLite uses WAL. Restart keeps turns, facts, and undelivered handoffs.

Configuration

ContextPolicy(
    mode=PolicyMode.PRIORITY_SELECTIVE,  # or FULL_HISTORY, WINDOWED, WINDOW_SUMMARY
    recency_turns=2,
    top_k=4,
    token_budget=4096,
    min_relevance=0.15,
    max_facts=12,
    tool_top_k=0,            # 0 = show every tool; >0 admits a subset
    max_result_tokens=0,     # 0 = verbatim tool results
    skill_top_k=0,           # 0 = all skill bodies; >0 manifests only
    min_handoff_relevance=0, # 0 = always display delivered packets
    max_handoff_tokens=256,
)

Optional environment:

Variable Default Meaning
CONTEXT_EXTRACTOR_MODEL groq/llama-3.1-8b-instant LiteLLM model for async fact extraction

Without extract (or if the LLM call fails) the engine uses a heuristic extractor. Without embed it uses BM25.

What this repo is

Path Ships in the wheel? Role
context_engine/ yes The product
tests/ no Unit tests for the product
examples/ no Integration sketches
eval/ no Phoenix eval harness (research)
docs/ no Design notes and measured results

eval/ and docs/research/ are how the layer was designed and measured. You do not need them to use the package.

Development

git clone https://github.com/hypen-code/aura.git
cd aura
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[embed,extract]"
python -m unittest discover -s tests -v

See CONTRIBUTING.md.

License

MIT. Contributions are welcome under the same license.

Cite / read more

Metadata

Release files for aura-context-engine 0.1.2

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

Source distribution (sdist)

Source distribution for aura-context-engine 0.1.2
File Size Uploaded Provenance
aura_context_engine-0.1.2.tar.gz 65.2 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for aura-context-engine 0.1.2
File Interpreter ABI Platform
aura_context_engine-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 126.1 kB

Release files / aura_context_engine-0.1.2.tar.gz

Download URL aura_context_engine-0.1.2.tar.gz
Size 65.2 kB
Tags Source
SHA-256 checksum
How to use checksums
69309408f6e4f27fa937fe0e256531e48cb9e376a2fa05b422e1761df5476387
BLAKE2b-256 checksum
How to use checksums
429f8c49fafad1cb3bda33b78f7e4c13df0a37f05475a648a73302abfe8c9d82
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 14, 2026.

Transparency log

Release files / aura_context_engine-0.1.2-py3-none-any.whl

Download URL aura_context_engine-0.1.2-py3-none-any.whl
Size 60.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
faa7fd4f20f1efdeab6e460ed3927d0abc628fa17a72abf323775e2b69ae9164
BLAKE2b-256 checksum
How to use checksums
58dd9fff0e92f8a35b51592732c728fd0e8e9907b5023132e5a4784bc246f866
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 14, 2026.

Transparency log

Security for aura-context-engine 0.1.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for aura_context_engine-0.1.2.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 14, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 release files Full provenance

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