- AI Engineering
- Posts
- Build AI Agents as Python Objects
Build AI Agents as Python Objects
... PLUS: Infinite Memory for Any AI Agent
In today’s newsletter:
Build AI Agents as Python Objects
Infinite Memory for Any AI Agent
Reading time: 5 minutes.
Most agent projects spread behavior across too many places.
The prompt lives in one file. Tool definitions live somewhere else. State sits in a graph or callback. Then the code for retries, events, and validation grows around all of it.
NVIDIA Labs’ new OO Agents paper proposes one Python object instead.
A class defines the agent. Its fields hold state. Its methods are actions. Docstrings provide instructions. Type annotations define what each action accepts and returns.
One Class Defines the Agent
NOOA makes the boundary between model behavior and normal code visible in the source file.
A method with a regular Python body is deterministic. It can parse data, call a database, calculate a value, or update state exactly as you would expect. A method with an ellipsis body, ..., is agentic. The framework turns that call into a validated LLM loop at runtime.
That gives developers a simple rule. Use an agentic method when a task needs model judgment. Use ordinary Python when the task has a defined implementation.
Types and Live Objects Keep Agents Grounded
Most agent frameworks turn tool inputs into serialized text or JSON. NOOA lets the model work with live Python objects through generated code.
The prompt gets a bounded preview of a large object. The object itself remains in the Python execution environment, so the model can inspect it, slice it, iterate over it, and pass it to other methods without placing the whole value in the context window.
Type annotations add another guardrail. When an agentic method returns a value, the runtime validates it against the declared return type. If the value does not match, the model gets an error and tries again before normal Python resumes.
The Harness Becomes Code
Context, event history, and state rendering often hide inside a framework runtime. NOOA exposes them as Python APIs that both developers and models can use.
That means the agent can inspect its own event history, work with model-visible state, and manage context through the same programming model used for the rest of the application. Prompts, tools, state, and deterministic code live in one place where engineers can test, trace, refactor, and review them.
The paper evaluates the approach on SWE-bench Verified, Terminal-Bench 2.0, and ARC-AGI-3. It also tests whether models can use the interface itself. Across 4,400 capability-test runs, the paper reports a 97.9% pass rate.
Agent reliability is often treated as a prompting problem. This paper makes a stronger case for treating it as a software design problem.
Every agent session starts from zero. Close the terminal, hit a compaction, or switch models, and everything the agent learned about your codebase and your preferences is gone.
OptMem is a memory that survives all of that. The whole integration is a 426-token prompt pasted into the agent's instructions file, plus one Python script with no dependencies. It passed 950 GitHub stars in its first week.
The interesting part isn't that OptMem stores memories. It's that nothing runs in the background to maintain them. The agent does that work itself, one small piece at a time, while it's already working.
Why a Memory File Stops Working
The obvious approach is a plain memory file the agent appends to. It's always loaded, costs zero tool calls, and works fine for a while.
The problem arrives a few hundred memories in. The file keeps growing, and every session pays for all of it in context. Eventually a meaningful slice of the context window is a note about a bug fixed in March.
Truncating the file fixes the cost and creates a worse problem. The oldest memories are exactly the ones that can't be reconstructed from the current session.
OptMem keeps every memory and reads only a summary of them.
Everything Is One Append-Only Log
Every memory is one line, capped at 280 characters, written to a single log file. Nothing in that file is ever edited or deleted. The agent adds one with a single command as it works.
Summaries live in a separate directory, and OptMem treats them as a disposable cache. If the summaries are lost or corrupted, they rebuild from the log alone. The log is the only thing that matters.
The Agent Does the Compressing
When memories pile up, something has to summarize them. Most memory tools hand that job to a background process or a second model.
OptMem hands it to the agent that's already running. Recording a memory sometimes returns a compression task in the same output.
The agent writes the summary and hands it back. Memories merge in pairs, then pairs of pairs, building a binary tree upward.
Nothing ever runs while the agent is idle. A background summarizer would mean a second model, a daemon, and a job that can fail quietly while the agent keeps working against stale memory. Folding the work into the agent's own turn removes all three.
Reading Costs the Same at Any Size
Every session starts by reading the memory. The number of lines that read prints is fixed, 96 by default, no matter how much history exists.
That budget holds because detail decays with age. Recent memories print verbatim. Older ones collapse into progressively larger summaries.
Running OptMem's own block selection at different history sizes shows how that works:
10 memories. All 10 print verbatim.
1,000 memories. 96 blocks, oldest collapsed 64 at a time, newest still verbatim.
100,000 memories. 96 blocks, oldest collapsed 8,192 at a time, newest still verbatim.
1,000,000 memories. 96 blocks, oldest collapsed 131,072 at a time, newest still verbatim.
The most recent memories stay individually readable at every scale. Only the distant past gets compressed, and it compresses harder the further back it goes.
Speed holds up for a different reason. Each log record is padded to exactly 320 bytes, so memory number 500,000 sits at a known byte offset. Reading it is one seek, not a scan. At a million memories the store is 608MB, and the read finishes in 0.03 seconds.
Compression is only lossy at read time. Two other commands get the detail back. One searches every memory ever written by regex, including memories currently hidden inside a summary. The other opens any summary into its two halves, and can keep going down to the original lines.
Subagents Are Told Not to Write
The prompt ends with a rule worth noticing. A subagent must never touch the memory at all.
The reasoning is that a subagent can't judge what the main agent already knows. Its notes would arrive duplicated and wrong. Parallel full sessions are fine, since each one reads the same memory and can judge for itself.
That distinction is the kind of thing you only find after watching a memory system fill up with garbage.
Most agent memory products are a service you run, a database you host, and a retrieval step you tune. OptMem is a text file, a prompt, and a script that hands the agent one small summarization job at a time.
That’s all for today. Thank you for reading today’s edition. See you in the next issue with more AI Engineering insights.
PS: We curate this AI Engineering content for free, and your support means everything. If you find value in what you read, consider sharing it with a friend or two.
Your feedback is valuable: If there’s a topic you’re stuck on or curious about, reply to this email. We’re building this for you, and your feedback helps shape what we send.
WORK WITH US
Looking to promote your company, product, or service to 200K+ AI developers? Get in touch today by replying to this email.



