-
-
Notifications
You must be signed in to change notification settings - Fork 67
Migrate from LangChain4j to LangChain4Clj #138
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Migrate from LangChain4j to LangChain4Clj #138
Conversation
Migrate from LangChain4j to langchain4clj - Replace ChatMessageSerializer/Deserializer with langchain4clj.messages - Replace ChatModelListener imports with langchain4clj.listeners - Remove unused chat-request->edn and edn->chat-request functions
Migrate from LangChain4j to LangChain4Clj
Migrate from LangChain4j to langchain4clj - Replace ChatMessageSerializer/Deserializer with langchain4clj.messages - Replace ChatModelListener imports with langchain4clj.listeners - Remove unused chat-request->edn and edn->chat-request functions
📝 WalkthroughWalkthroughThis pull request migrates the LangChain integration from direct LangChain4j dependencies to a new Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant CLI as prompt_cli
participant Agent as general_agent
participant Memory as Memory<br/>(chain)
participant Tools as Tools<br/>(chain)
participant Model as Model<br/>(lc/create-model)
participant Assistant as Assistant Fn
User->>CLI: Input prompt + context
CLI->>Agent: create-general-agent(config)
rect rgb(240, 248, 255)
Note over Agent,Assistant: Agent Initialization
Agent->>Model: lc/create-model(config)
Model-->>Agent: model instance
Agent->>Memory: chat-memory()
Memory-->>Agent: memory instance
Agent->>Memory: memory-add!(system-message)
Agent->>Tools: convert-tools(tool-specs)
Tools-->>Agent: tool-map
Agent->>Assistant: create-assistant-fn(model, memory, tools, system-msg)
Assistant-->>Agent: assistant-fn
Agent-->>CLI: {assistant-fn, memory, model, tools, ...}
end
rect rgb(255, 240, 245)
Note over CLI,Assistant: Chat Invocation
CLI->>Agent: chat-with-agent(agent, prompt)
Agent->>Memory: memory-count()
Memory-->>Agent: count
alt count > MEMORY-RESET-BUFFER
Agent->>Memory: memory-clear!()
Agent->>Memory: memory-add!(context)
end
Agent->>Assistant: assistant-fn(prompt)
Assistant->>Memory: memory-add!(prompt)
Assistant->>Model: invoke with memory
Model-->>Assistant: response
Assistant->>Memory: memory-add!(response)
Assistant-->>Agent: result
Agent-->>CLI: response
end
CLI->>User: Output response
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🧹 Nitpick comments (3)
deps.edn (1)
98-98: Redundant nrepl dependency declaration.
nrepl/nreplis now declared in main:deps(line 4), making this:extra-depsentry redundant for the:nreplalias. Consider removing it to avoid version drift.Proposed fix
:nrepl {:extra-paths ["test" "dev"] - :extra-deps {nrepl/nrepl {:mvn/version "1.3.1"}} :main-opts ["-m" "nrepl.cmdline" "--port" "7888"]}src/clojure_mcp/agent/general_agent.clj (1)
140-145: Consider extracting the threshold buffer as a named constant.The magic number
15in(- memory-size 15)represents a buffer before triggering reset. For clarity, consider extracting this to a constant likeMEMORY-RESET-BUFFER.🔎 Proposed refactor
(def DEFAULT-MEMORY-SIZE 100) (def DEFAULT-STATELESS-BUFFER 100) (def MIN-PERSISTENT-WINDOW 10) +(def MEMORY-RESET-BUFFER 15)Then use:
- (if (> (chain/memory-count memory) (- memory-size 15)) + (if (> (chain/memory-count memory) (- memory-size MEMORY-RESET-BUFFER))src/clojure_mcp/agent/langchain.clj (1)
128-136: Consider making max-iterations configurable.The
max-iterationsis hardcoded to 10. While this is a reasonable default, consider making it configurable for agents that may need more iterations for complex tool chains.🔎 Proposed refactor
-(defn create-assistant-fn [{:keys [model memory tools system-message]}] +(defn create-assistant-fn [{:keys [model memory tools system-message max-iterations] + :or {max-iterations 10}}] (assistant/create-assistant {:model model :memory memory :tools (when (seq tools) (convert-tools tools)) :system-message system-message - :max-iterations 10})) + :max-iterations max-iterations}))
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
CHANGELOG.mddeps.ednsrc/clojure_mcp/agent/general_agent.cljsrc/clojure_mcp/agent/langchain.cljsrc/clojure_mcp/agent/langchain/chat_listener.cljsrc/clojure_mcp/agent/langchain/message_conv.cljsrc/clojure_mcp/agent/langchain/model.cljsrc/clojure_mcp/agent/langchain/schema.cljsrc/clojure_mcp/prompt_cli.cljtest/clojure_mcp/agent/general_agent_test.cljtest/clojure_mcp/agent/langchain/model_test.cljtest/clojure_mcp/agent/langchain/schema_test.cljtest/clojure_mcp/config/tools_config_test.clj
💤 Files with no reviewable changes (2)
- test/clojure_mcp/agent/langchain/schema_test.clj
- src/clojure_mcp/agent/langchain/schema.clj
🧰 Additional context used
📓 Path-based instructions (2)
**/*.clj
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.clj: Use:requirewith ns aliases in import statements (e.g.,[clojure.string :as string])
Use kebab-case for variable and function names
End predicate functions with?(e.g.,is-top-level-form?)
Usetry/catchwith specific exception handling; use atom for tracking errors
Use 2-space indentation and maintain whitespace in edited forms
Align namespace names with directory structure (e.g.,clojure-mcp.repl-toolsforclojure_mcp/repl_tools.clj)
Include clear tool:descriptionfor LLM guidance in MCP tool definitions
Validate inputs and provide helpful error messages in MCP tools
Return structured data with both result and error status from MCP tools
Maintain atom-based state for consistent service access in MCP tools
Files:
src/clojure_mcp/prompt_cli.cljsrc/clojure_mcp/agent/langchain.cljsrc/clojure_mcp/agent/langchain/chat_listener.cljsrc/clojure_mcp/agent/langchain/message_conv.cljtest/clojure_mcp/agent/langchain/model_test.cljtest/clojure_mcp/config/tools_config_test.cljtest/clojure_mcp/agent/general_agent_test.cljsrc/clojure_mcp/agent/general_agent.cljsrc/clojure_mcp/agent/langchain/model.clj
**/*_test.clj
📄 CodeRabbit inference engine (CLAUDE.md)
Use
deftestwith descriptive test names; usetestingfor subsections; useisfor assertions
Files:
test/clojure_mcp/agent/langchain/model_test.cljtest/clojure_mcp/config/tools_config_test.cljtest/clojure_mcp/agent/general_agent_test.clj
🧠 Learnings (5)
📚 Learning: 2025-12-07T23:16:26.445Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T23:16:26.445Z
Learning: Applies to **/*.clj : Include clear tool `:description` for LLM guidance in MCP tool definitions
Applied to files:
src/clojure_mcp/prompt_cli.cljdeps.edntest/clojure_mcp/config/tools_config_test.clj
📚 Learning: 2025-12-07T23:16:26.445Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T23:16:26.445Z
Learning: Applies to **/*.clj : Maintain atom-based state for consistent service access in MCP tools
Applied to files:
src/clojure_mcp/prompt_cli.cljdeps.ednCHANGELOG.mdtest/clojure_mcp/agent/general_agent_test.cljsrc/clojure_mcp/agent/general_agent.clj
📚 Learning: 2025-12-07T23:16:26.445Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T23:16:26.445Z
Learning: Applies to **/*.clj : Return structured data with both result and error status from MCP tools
Applied to files:
src/clojure_mcp/prompt_cli.cljtest/clojure_mcp/config/tools_config_test.clj
📚 Learning: 2025-12-07T23:16:26.445Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T23:16:26.445Z
Learning: Applies to **/*.clj : Align namespace names with directory structure (e.g., `clojure-mcp.repl-tools` for `clojure_mcp/repl_tools.clj`)
Applied to files:
deps.edntest/clojure_mcp/config/tools_config_test.clj
📚 Learning: 2025-12-07T23:16:26.445Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T23:16:26.445Z
Learning: Applies to **/*.clj : Use `:require` with ns aliases in import statements (e.g., `[clojure.string :as string]`)
Applied to files:
test/clojure_mcp/config/tools_config_test.clj
🔇 Additional comments (34)
deps.edn (1)
24-26: Dependency consolidation looks good.The migration from multiple LangChain4j Maven artifacts to a single langchain4clj dependency aligns with PR objectives and simplifies dependency management. The comment clearly documents that LangChain4j classes remain available transitively.
src/clojure_mcp/agent/langchain/chat_listener.clj (2)
37-47: Breaking change clearly documented.The docstring properly documents the atom structure change, providing both old and new formats and guidance for consumers. This helps with migration.
49-51: Simple re-export ofcompose-listeners.Using
defto alias the function is idiomatic Clojure for re-exporting without wrapping.test/clojure_mcp/config/tools_config_test.clj (2)
4-5: Imports updated correctly for langchain4clj migration.The
modelnamespace is retained forget-tool-modelcalls whilelc/*env-overrides*is properly used for environment binding.
43-51: Environment override binding migrated correctly.The test now uses
lc/*env-overrides*for test API key injection, consistent with the langchain4clj wrapper approach.src/clojure_mcp/prompt_cli.clj (4)
14-22: Imports updated for langchain4clj message handling.The namespace now properly uses
langchain4clj.messagesfor serialization and thechainalias for memory operations. Import organization follows coding guidelines with:requirealiases.
89-89: Message serialization delegated to langchain4clj.Using
lc-messages/messages->jsonaligns with the migration objective to remove direct Java interop.
118-118: Message deserialization delegated to langchain4clj.Using
lc-messages/json->messagesfor loading sessions is consistent with the serialization path.
367-368: Memory addition uses new chain helper.
chain/memory-add!replaces direct Java memory manipulation, consistent with the memory-centric API migration.src/clojure_mcp/agent/langchain/message_conv.clj (3)
1-5: Clean namespace simplification.The docstring accurately describes the purpose, and requires are minimal—only what's needed for JSON handling and langchain4clj message conversion.
7-18: JSON round-trip approach is straightforward.The conversion via JSON intermediary is clear and delegates complexity to langchain4clj. This eliminates the need for custom serialization logic.
20-34: Single-message converters properly handle nil.Using
some->ensures nil messages don't cause exceptions during conversion.CHANGELOG.md (1)
5-31: Comprehensive changelog entry for the migration.The entry clearly documents the migration scope, breaking changes (with before/after examples for the token-tracking listener), and removed components. This will help consumers understand the impact and migrate their code.
test/clojure_mcp/agent/langchain/model_test.clj (3)
1-11: Test imports updated for langchain4clj migration.The test properly imports both the Clojure wrapper (
langchain4clj.presets,langchain4clj.core) and the underlying Java model classes for type assertions.
30-67: Thorough test coverage for model creation from config.Tests cover user config precedence, preset fallback with API key override, Anthropic models, and error handling for unknown model keys. Good coverage of the key scenarios.
81-93: Backward compatibility test for legacy:model-namekey.This test ensures existing configs using
:model-namecontinue to work after the migration to langchain4clj which expects:model. Good migration safety check.test/clojure_mcp/agent/general_agent_test.clj (4)
6-8: Test imports updated for langchain4clj integration.Properly imports
langchain4clj.coreandlangchain4clj.presetsfor model creation in tests.
38-50: Memory tests migrated to use new helpers.Tests now use
chain/memory-countandchain/memory-messagesinstead of direct memory field access, aligning with the memory-centric API.
71-87: Agent creation test updated for new API.Model creation uses
lc/create-modelwith presets, and the test correctly expects:assistant-fnin the returned agent map (replacing the previous:servicekey per the PR summary).
116-126: Context update test uses memory helpers.The test properly uses
chain/memory-add!andchain/memory-countfor memory operations, consistent with the migration.src/clojure_mcp/agent/general_agent.clj (7)
1-13: LGTM - Namespace and constants are well-defined.The namespace declaration follows guidelines with proper
:requireand ns aliases. The constantsDEFAULT-MEMORY-SIZE,DEFAULT-STATELESS-BUFFER, andMIN-PERSISTENT-WINDOWare appropriately named using SCREAMING-KEBAB-CASE for constants.
88-113: LGTM - Clean conditional logic for memory configuration.The function properly handles the three memory modes (stateless default, stateless for small values, persistent window) with clear conditions and appropriate use of the
MIN-PERSISTENT-WINDOWconstant.
115-129: LGTM - Clean migration to langchain4clj memory API.The function now uses
chain/memory-add!with an idiomatic EDN map representation instead of direct Java interop, improving readability.
147-199: LGTM - Well-structured agent creation with proper validation.The function correctly validates required parameters, creates the assistant function using the new langchain4clj wrapper, and returns a comprehensive agent map. The docstring accurately documents the breaking change from
:serviceto:assistant-fn.
201-234: LGTM - Clean chat invocation with proper error handling.The function correctly handles blank prompts, manages memory for both stateless and persistent modes, and invokes the assistant function properly. The structured return with
:resultand:errorfollows the coding guidelines.
236-247: LGTM - Simple and effective context update.The function correctly clears memory, reinitializes with new context, and returns the updated agent map.
249-262: LGTM - Correct agent recreation for tool addition.The docstring clearly notes that adding tools requires recreating the agent. The
select-keysproperly preserves only the configuration keys needed for recreation.src/clojure_mcp/agent/langchain.clj (3)
1-10: LGTM - Clean namespace declaration following guidelines.Proper use of
:requirewith ns aliases as per coding guidelines. The docstring clearly describes the adapter's purpose.
14-36: LGTM - Idiomatic memory wrapper functions.The memory functions properly wrap the langchain4clj assistant API. Function names with
!suffix correctly indicate side effects. Thememory-add!function appropriately handles both map and message object inputs.
88-104: LGTM - Well-structured tool conversion with proper validation.The preconditions validate inputs, and the function correctly handles schema as either a JSON string or a map. The conversion to langchain4clj format is clean.
src/clojure_mcp/agent/langchain/model.clj (4)
1-7: LGTM - Clean namespace declaration.The namespace declaration follows guidelines with proper requires and aliases.
22-33: LGTM - Proper Long to Integer coercion for Java interop.The
coerce-integersfunction correctly handles the type coercion needed for LangChain4j's Java API, which expects Integer rather than Long for certain parameters.
51-73: LGTM - Robust model creation with proper error handling and security.The function correctly:
- Falls back from user-models to presets
- Provides informative error with available options
- Excludes
:api-keyfrom debug logging (good security practice)- Applies proper config normalization
75-88: LGTM - Graceful handling of missing or failed tool model configuration.The function uses
when-letchain for safe nil handling and catches exceptions to log warnings rather than propagating, allowing callers to handle missing models gracefully.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/clojure_mcp/agent/general_agent.clj (1)
253-266: Fix key mismatch inadd-tools.Line 265 selects
:system-promptfrom the agent map, butcreate-general-agentreturns:system-message(line 197). This mismatch will causeadd-toolsto passnilfor:system-prompt, triggering the validation error at line 175.🔎 Proposed fix
(defn add-tools "Add additional tools to an existing agent. Note: This requires recreating the agent. Args: - agent: The agent map - new-tools: Vector of new tools to add Returns: A new agent map with additional tools" [agent new-tools] (create-general-agent (-> agent - (select-keys [:system-prompt :context :model :memory-size]) + (select-keys [:system-message :context :model :memory-size]) + (clojure.set/rename-keys {:system-message :system-prompt}) (assoc :tools (vec (concat (:tools agent) new-tools))))))
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
deps.ednsrc/clojure_mcp/agent/general_agent.cljsrc/clojure_mcp/agent/langchain.cljsrc/clojure_mcp/agent/langchain/chat_listener.clj
🚧 Files skipped from review as they are similar to previous changes (1)
- deps.edn
🧰 Additional context used
📓 Path-based instructions (1)
**/*.clj
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.clj: Use:requirewith ns aliases in import statements (e.g.,[clojure.string :as string])
Use kebab-case for variable and function names
End predicate functions with?(e.g.,is-top-level-form?)
Usetry/catchwith specific exception handling; use atom for tracking errors
Use 2-space indentation and maintain whitespace in edited forms
Align namespace names with directory structure (e.g.,clojure-mcp.repl-toolsforclojure_mcp/repl_tools.clj)
Include clear tool:descriptionfor LLM guidance in MCP tool definitions
Validate inputs and provide helpful error messages in MCP tools
Return structured data with both result and error status from MCP tools
Maintain atom-based state for consistent service access in MCP tools
Files:
src/clojure_mcp/agent/langchain/chat_listener.cljsrc/clojure_mcp/agent/general_agent.cljsrc/clojure_mcp/agent/langchain.clj
🧠 Learnings (6)
📚 Learning: 2025-12-07T23:16:26.445Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T23:16:26.445Z
Learning: Applies to **/*.clj : Use `try/catch` with specific exception handling; use atom for tracking errors
Applied to files:
src/clojure_mcp/agent/langchain/chat_listener.clj
📚 Learning: 2025-12-27T06:54:07.157Z
Learnt from: nandoolle
Repo: bhauman/clojure-mcp PR: 138
File: src/clojure_mcp/agent/langchain/model.clj:91-97
Timestamp: 2025-12-27T06:54:07.157Z
Learning: When reviewing Clojure code (e.g., in src/clojure_mcp/... ), verify calls to presets/get-preset follow the two arities: [preset-key] and [preset-key overrides]. The 2-arg version should merge the provided overrides map with the preset defaults and return the resulting configuration. Check for correct map merging, preservation of immutability, and validation of overrides keys to ensure predictable configuration outcomes.
Applied to files:
src/clojure_mcp/agent/langchain/chat_listener.cljsrc/clojure_mcp/agent/general_agent.cljsrc/clojure_mcp/agent/langchain.clj
📚 Learning: 2025-12-07T23:16:26.445Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T23:16:26.445Z
Learning: Applies to **/*.clj : Maintain atom-based state for consistent service access in MCP tools
Applied to files:
src/clojure_mcp/agent/general_agent.clj
📚 Learning: 2025-12-07T23:16:26.445Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T23:16:26.445Z
Learning: Applies to **/*.clj : Include clear tool `:description` for LLM guidance in MCP tool definitions
Applied to files:
src/clojure_mcp/agent/general_agent.clj
📚 Learning: 2025-12-27T06:53:25.104Z
Learnt from: nandoolle
Repo: bhauman/clojure-mcp PR: 138
File: src/clojure_mcp/agent/langchain.clj:46-57
Timestamp: 2025-12-27T06:53:25.104Z
Learning: For src/clojure_mcp/agent/langchain.clj, when upgrading to langchain4clj 1.6.1, use the reasoning model presets :anthropic/claude-sonnet-4-reasoning, :google/gemini-2-5-flash-reasoning, or :openai/o4-mini-reasoning. These presets produce valid configurations containing a :thinking map; verify that the resulting configuration includes a :thinking key and aligns with the expected schema before use.
Applied to files:
src/clojure_mcp/agent/langchain.clj
📚 Learning: 2025-12-07T23:16:26.445Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T23:16:26.445Z
Learning: Applies to **/*.clj : Return structured data with both result and error status from MCP tools
Applied to files:
src/clojure_mcp/agent/langchain.clj
🔇 Additional comments (15)
src/clojure_mcp/agent/langchain/chat_listener.clj (3)
7-28: LGTM! Consistent:ctxhandling across all handlers.The
on-request,on-response, andon-errorhandlers now consistently attach:ctxfrom:raw-contextfor backward compatibility. This resolves the inconsistency previously flagged.
30-35: LGTM!Clean delegation to
lc-listeners/logging-listenerwith appropriate two-arity wrapper.
37-51: LGTM! Breaking change is well-documented.The docstring clearly documents the atom structure change from legacy keys (
:total-input-tokens,:total-output-tokens) to current keys (:input-tokens,:output-tokens), guiding consumers to update their code accordingly.src/clojure_mcp/agent/langchain.clj (6)
16-35: LGTM! Clean memory API delegation.Memory functions properly delegate to
langchain4clj.assistantwith appropriate handling of both map and object message types inmemory-add!.
39-67: LGTM! Model creation with appropriate fallback handling.The model creation flow properly detects available providers via environment variables and returns
nilwhen no provider is configured, allowing callers to handle the absence gracefully. The reasoning model presets are confirmed to exist in langchain4clj 1.6.1 per previous verification.
71-90: LGTM! Timeout prevents indefinite blocking.The 5-minute timeout on
deref(line 87-89) appropriately prevents indefinite blocking if the callback-style tool function never invokes its callback, addressing the concern from previous review feedback.
92-130: LGTM! Robust tool conversion with validation.The tool conversion functions include proper precondition validation (lines 95-96) and handle both string (JSON) and map schema formats. The separation between standard tool-map format and AiServices format is clean and appropriate.
134-150: LGTM! Clean assistant creation with sensible defaults.The function properly defaults
max-iterationsto 10 and only converts tools when non-empty (line 148), avoiding unnecessary conversion overhead and potential nil issues.
154-158: LGTM! Clean message helper functions.The message helpers appropriately delegate to
messages/edn->messagewith proper type handling, coercing content to string inuser-messagewhen needed.src/clojure_mcp/agent/general_agent.clj (6)
15-17: LGTM! Clear constant definition.The
MEMORY-RESET-BUFFERconstant is well-documented and appropriately scoped for use in memory management logic.
119-133: LGTM! Context initialization with clean delegation.The function properly combines context strings and delegates to
chain/memory-add!with the appropriate message structure.
135-149: LGTM! Proactive memory reset with buffer.The function uses
MEMORY-RESET-BUFFERto trigger reset before reaching the limit, preventing potential overflow issues while preserving conversation coherence by re-initializing with context.
151-203: LGTM! Agent creation with proper validation and delegation.The function validates required inputs (model and system-prompt), creates memory based on configuration, and properly initializes the assistant via
chain/create-assistant-fn. Note that the returned map uses:system-messagewhile the input uses:system-prompt.
205-238: LGTM! Proper memory management and assistant invocation.The function correctly handles stateless vs. persistent memory modes, uses
chain/memory-clear!for stateless agents, and invokes the:assistant-fnappropriately. Memory reset logic for persistent agents prevents overflow while maintaining context.
240-251: LGTM! Clean context update with memory refresh.The function properly clears and re-initializes memory with the new context, returning an updated agent map.
5745111 to
7428fdf
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/clojure_mcp/agent/langchain.clj (1)
59-67: Document that these functions can returnnilwhen no API key is configured.Both
agent-modelandreasoning-agent-modelwill returnnilif no supported API key environment variable is set. Whilecreate-general-agentingeneral_agent.cljchecks for nil models, the docstrings should explicitly state this return behavior to help callers handle the case properly.🔎 Suggested docstring additions
(defn agent-model [] + "Creates a chat model using the first available provider. + + Detects provider based on environment variables: + - ANTHROPIC_API_KEY, GEMINI_API_KEY, or OPENAI_API_KEY + + Returns the model instance, or nil if no API key is configured." (when-let [provider (detect-available-provider)] (when-let [model-key (default-model-for-provider provider false)] (lc/create-model (presets/get-preset model-key))))) (defn reasoning-agent-model [] + "Creates a reasoning-capable chat model using the first available provider. + + Detects provider based on environment variables: + - ANTHROPIC_API_KEY, GEMINI_API_KEY, or OPENAI_API_KEY + + Returns the model instance, or nil if no API key is configured." (when-let [provider (detect-available-provider)] (when-let [model-key (default-model-for-provider provider true)] (lc/create-model (presets/get-preset model-key)))))
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
deps.ednsrc/clojure_mcp/agent/general_agent.cljsrc/clojure_mcp/agent/langchain.cljsrc/clojure_mcp/agent/langchain/chat_listener.clj
🚧 Files skipped from review as they are similar to previous changes (1)
- deps.edn
🧰 Additional context used
📓 Path-based instructions (1)
**/*.clj
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.clj: Use:requirewith ns aliases in import statements (e.g.,[clojure.string :as string])
Use kebab-case for variable and function names
End predicate functions with?(e.g.,is-top-level-form?)
Usetry/catchwith specific exception handling; use atom for tracking errors
Use 2-space indentation and maintain whitespace in edited forms
Align namespace names with directory structure (e.g.,clojure-mcp.repl-toolsforclojure_mcp/repl_tools.clj)
Include clear tool:descriptionfor LLM guidance in MCP tool definitions
Validate inputs and provide helpful error messages in MCP tools
Return structured data with both result and error status from MCP tools
Maintain atom-based state for consistent service access in MCP tools
Files:
src/clojure_mcp/agent/langchain.cljsrc/clojure_mcp/agent/general_agent.cljsrc/clojure_mcp/agent/langchain/chat_listener.clj
🧠 Learnings (5)
📚 Learning: 2025-12-27T06:53:25.104Z
Learnt from: nandoolle
Repo: bhauman/clojure-mcp PR: 138
File: src/clojure_mcp/agent/langchain.clj:46-57
Timestamp: 2025-12-27T06:53:25.104Z
Learning: For src/clojure_mcp/agent/langchain.clj, when upgrading to langchain4clj 1.6.1, use the reasoning model presets :anthropic/claude-sonnet-4-reasoning, :google/gemini-2-5-flash-reasoning, or :openai/o4-mini-reasoning. These presets produce valid configurations containing a :thinking map; verify that the resulting configuration includes a :thinking key and aligns with the expected schema before use.
Applied to files:
src/clojure_mcp/agent/langchain.clj
📚 Learning: 2025-12-07T23:16:26.445Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T23:16:26.445Z
Learning: Applies to **/*.clj : Return structured data with both result and error status from MCP tools
Applied to files:
src/clojure_mcp/agent/langchain.clj
📚 Learning: 2025-12-27T06:54:07.157Z
Learnt from: nandoolle
Repo: bhauman/clojure-mcp PR: 138
File: src/clojure_mcp/agent/langchain/model.clj:91-97
Timestamp: 2025-12-27T06:54:07.157Z
Learning: When reviewing Clojure code (e.g., in src/clojure_mcp/... ), verify calls to presets/get-preset follow the two arities: [preset-key] and [preset-key overrides]. The 2-arg version should merge the provided overrides map with the preset defaults and return the resulting configuration. Check for correct map merging, preservation of immutability, and validation of overrides keys to ensure predictable configuration outcomes.
Applied to files:
src/clojure_mcp/agent/langchain.cljsrc/clojure_mcp/agent/general_agent.cljsrc/clojure_mcp/agent/langchain/chat_listener.clj
📚 Learning: 2025-12-07T23:16:26.445Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T23:16:26.445Z
Learning: Applies to **/*.clj : Maintain atom-based state for consistent service access in MCP tools
Applied to files:
src/clojure_mcp/agent/general_agent.clj
📚 Learning: 2025-12-07T23:16:26.445Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T23:16:26.445Z
Learning: Applies to **/*.clj : Use `try/catch` with specific exception handling; use atom for tracking errors
Applied to files:
src/clojure_mcp/agent/langchain/chat_listener.clj
issue addressed |
Summary
This PR replaces direct LangChain4j Java imports with the LangChain4Clj Clojure wrapper library, significantly simplifying the codebase while maintaining full backward compatibility.
Motivation
Dependencies:
Breaking Changes
token-tracking-listener atom structure changed:
This is documented in the function's docstring. Consumers should update to use :input-tokens/:output-tokens keys.
Backward Compatibility
Summary by CodeRabbit
Refactor
New Features
Tests
✏️ Tip: You can customize this high-level summary in your review settings.