Skip to content

OpenAI compatibility#21

Open
jtoman wants to merge 3 commits into
masterfrom
jtoman/openai-memory-backend
Open

OpenAI compatibility#21
jtoman wants to merge 3 commits into
masterfrom
jtoman/openai-memory-backend

Conversation

@jtoman
Copy link
Copy Markdown
Contributor

@jtoman jtoman commented Jun 1, 2026

  • Changes shape of input schema for memory tools targeting openAI. We need to actually define a proper schema, as gpt-5.* don't have some built in schema its trained on
  • re-introduce the invoke and ainvoke wrappers to paper over the difference in input list schemas (anthropic allows bare strings in lists, openai doesn't)
  • paper over "standardized" token usage format from LC. Exposed as a new entrypoint to not break existing upstream users.

jtoman added 3 commits May 26, 2026 17:01
Keeps a singular tool, but with a more structured tool schema. The "flat
schema of all possible fields" is an artifact of trying to fit
anthropic's internal schema into langgraph's infrastructure. OpenAI
we're defining the tooling, so we can do better.
Paper over differences in "standardized" (lol) usage metrics, and
normalize `list[dict | str]` and `list[dict]` (openai doesn't let you
intermix string and dicts within a list of content, booo)
@jtoman jtoman requested a review from naftali-g June 1, 2026 20:58
Comment thread graphcore/tools/memory.py

def _dispatch_openai_op[R](
backend: MemoryToolImpl[R],
op: _CreateOp | _ViewOp | _StrReplaceOp | _InsertOp | _DeleteOp | _RenameOp,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
op: _CreateOp | _ViewOp | _StrReplaceOp | _InsertOp | _DeleteOp | _RenameOp,
op: _MemoryOpUnion,

?

Comment thread graphcore/tools/memory.py
Comment on lines +1383 to +1384
if vr is not None and len(vr) >= 2:
rng = (vr[0], vr[1])
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there validation somewhere that this is either None or of length exactly 2?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

er, no, I guess we can tighten the validation here.

Comment thread graphcore/tools/memory.py
range = (args.view_range[0], args.view_range[1])
return backend.view(args.path, range)

def async_memory_tool(backend: MemoryToolImpl[Awaitable[str]]) -> BaseTool:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you want to rename this to async_anthropic_memory_tool or something?

Comment thread graphcore/tools/memory.py
)
return MemoryTool.as_tool("memory")

def memory_tool(backend: MemoryToolImpl[str]) -> BaseTool:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Comment thread graphcore/utils.py
return to_ret

to_ret["total_input_tokens"] = usage["input_tokens"]
to_ret["total_output_tokens"] = usage["output_tokens"]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so the logic here is different than before - total used to be input+chached, now it's just input. Why the change?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous logic we had would pull from anthropic specific response metadata. langchain actually exposes a "normalized" token usage metadata object, but its definition of "input tokens" is different from anthropic. Namely, what anthropic calls input tokens are "all tokens which aren't cache writes or reads." Langchain's "input tokens" are "all input tokens" (regardless of cache status); each model provider integration in LC writes code to translate the provider specific metadata to this representation. We want to move to provider agnostic code where possible, but I wasn't willing to break BC and change the meaning of "input tokens" in the existing APIs. Hence this new api, and the new interpretation of "input tokens" (to match LC).

Comment thread graphcore/tools/memory.py
"""


def openai_async_memory_tool(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I probably just don't understand at all this implementation, but I expected there to be some abstraction layer that dispatches to the correct memory_tool implementation depending on the model. Where is that going to live?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, its all upstream: Certora/AIComposer#105

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants