Skip to content

feat: OCG-backed agent long-term memory#126

Open
NicholasDCole wants to merge 1 commit into
feature/combine-agentspanfrom
feature/add_memory
Open

feat: OCG-backed agent long-term memory#126
NicholasDCole wants to merge 1 commit into
feature/combine-agentspanfrom
feature/add_memory

Conversation

@NicholasDCole

Copy link
Copy Markdown

Ports the SDK side of the agentspan "OCG-backed agent memory" feature (agentspan-ai/agentspan#298) to the Java SDK. The server-side compiler that consumes the wire fields emitted here lives in conductor-oss/conductor (agentspan-server: LongTermMemoryConfig.java, AgentConfig.longTermMemory/feedbackSink).

What was ported

Agent params (conductor-ai/.../Agent.java)

  • semanticMemory(SemanticMemory) — the memory store handle
  • memorySummaryModel(String) — optional model override for the distiller
  • feedbackSink(Consumer<FeedbackEvent>) — receives the good/bad capability links out-of-band

Serializer emission (conductor-ai/.../internal/AgentConfigSerializer.java) — the most important piece; the server only activates the feature when this is emitted:

  • longTermMemory: {ocgUrl, credential, agent, user, scope, maxResults, summaryModel}, camelCase, null-valued keys omitted. credential is a server-resolvable secret NAME (default OCG_PUBLIC_KEY), never the raw client token. summaryModel falls back to the agent's model. Emitted only when the store is an OCGMemoryStore.
  • feedbackSink: {taskName: "<agent>_feedback_sink"}, emitted only when a feedbackSink is set alongside OCG memory.

OCGMemoryStore (conductor-ai/.../model/OCGMemoryStore.java) — synchronous MemoryStore HTTP adapter over the OCG BFF: searchPOST /api/v1/memories/search; addPOST /api/v1/memories; deleteDELETE; listAllGET; feedbackLinks(key)POST /api/v1/memories/{key}/feedback-links. Auth via Authorization: Bearer <token>. Search folds the human good/bad signal (and bad-verdict reasons) into result content. Built on the JDK HttpClient (the convention already used by ServerlessCodeExecutor/GPTAssistantAgent), with a pluggable Transport seam so tests can capture requests and serve canned responses — the Java equivalent of the Python tests' httpx.MockTransport.

Supporting types (conductor-ai/.../model/) — MemorySummary (structured summarizer output), FeedbackEvent (distilled summary + signed URLs), and OCGMemoryStore.buildMemorySummarizer(...) (recursion-safe internal summarizer sub-agent, built without semanticMemory).

ExampleExample118OcgMemory.java, mirroring Python's 118_ocg_memory.py.

Java-specific adaptations

  • The Python store detects "OCG-backed" via a private _base attribute; the Java serializer uses store instanceof OCGMemoryStore, which is cleaner and typed.
  • feedback_sink (a Python callable) maps to Consumer<FeedbackEvent>.
  • MemorySummary (pydantic model) maps to a plain POJO used as the summarizer's outputType.
  • HTTP client is the JDK HttpClient + Jackson (JsonMapper), not httpx.
  • SemanticMemory gained a getStore() accessor so the serializer can inspect the backing store.

What was skipped, and why

Runtime pre/post-run wiring is not ported. The Java AgentRuntime.run() has no client-side agent turn loop equivalent to Python's runtime.py — it serializes the agent and delegates the entire run to the server (startAgent + wait for result). There is no client-side point at which to inject retrieved memories into a copy of the instructions or to run a post-run summarizer/save. On the deployed path this is exactly what the emitted longTermMemory config drives server-side. Consequently the Python runtime.py save/retrieval hook unit tests are not translated; the store, summary, and serializer tests are. Registering a <agent>_feedback_sink worker for the compiled path is a natural follow-up (it belongs to that same runtime-wiring surface).

Tests

./gradlew :conductor-ai:test286 tests, 0 failures, 0 errors, 10 skipped. New: OcgMemoryStoreTest (8) and 4 additions to SerializerTest (58 total). spotlessCheck passes.

🤖 Generated with Claude Code

Port the agentspan "OCG-backed agent memory" feature to the Java SDK.

- Agent gains semanticMemory / memorySummaryModel / feedbackSink params
- AgentConfigSerializer emits longTermMemory + feedbackSink on the wire
  (camelCase, omitted when unset) so the server-side compiler activates
  retrieval + distill/save/feedback on the deployed path
- OCGMemoryStore: synchronous MemoryStore HTTP adapter over the OCG BFF
  (search / add / delete / listAll + feedback-links mint), built on the
  JDK HttpClient with a pluggable Transport seam for tests
- MemorySummary + FeedbackEvent + buildMemorySummarizer for parity
- Unit tests (OcgMemoryStoreTest, SerializerTest additions) + Example118

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant