LangGraph4j release stream
1.9 currently in active development. The implementation is centered on [
SkilledReactSubAgent], which turns a markdown skill into both:
- a compiled LangGraph4j sub-graph
- a Spring AI tool (i.e.
ToolCallback)
That means the same component can participate in the graph as an agent and present itself to the parent LLM as a callable tool.
In particular the flow is:
- Parse the
SKILL.md
- Extract
name and description from front matter
- Optionally filter tools using
allowed-tools
- Use the markdown body as the sub-agent instructions
- Compile the agent
- Wrap it into a function tool whose input is a single
context field
The important design choice is that the tool definition is derived from the skill metadata, while the agent behavior is derived from the skill content.
Skill Format
The supported skill format is
---
name: <agent name>
description: "|"
<multi line description>
allowed-tools: <list of tools>
---
<skill body>
From Skill to Tool-Backed Agent
The conversion happens in SkilledReactSubAgent.Builder#build(...). This is the crucial bridge where:
- the skill metadata defines the external API
- the skill body defines the internal operating behavior
- the allowed tools define the sub-agent execution boundary
The resulting agent is then wrapped as a Spring AI function tool.
From the parent agent point of view, this is just another tool. Internally, it is a complete ReAct-capable agent workflow.
Examples
Purchase Assistant Agent
This is an agent that allow to select a produdct from a reference marketplace and purchase it. Below the simplified component diagram.
diagram
Marketplace Skill
---
name: agent-marketplace
description: |
marketplace agent, ask for information about products. This is agent that provides the information on the product marketplace.
required data are:
* product name
allowed-tools: searchByProduct
---
## Retrieve product information
We need all information about about the product of interest in particular is mandatory to have
* product name
with such information we have to invoke tool `searchByProduct` and return the result
Payment Skill
---
name: agent-payment
description: |
payment agent, this is the agent that provides payment service.
required data are:
* Product name
* Product price
* Product currency
* the International Bank Account Number (IBAN) - optional
allowed-tools:
- submit-payment
- retrieve-iban
---
## submit a payment for purchasing a specific product
We need all information about purchasing to allow the payment
* Product name
* Product price
* Product price currency
* International Bank Account Number (IBAN)
With such information you must invoke tool `submit-payment` and return the result of the payment transaction plus the IBAN.
If IBAN is not provided invoke tool `retrieve-iban` to retrieve the required IBAN.
Observing the skills above they define three different concerns:
-
name: the tool name exposed to the parent agent
-
description: the tool description shown to the model
-
allowed-tools: the only tools available inside the sub-agent
Everything after the front matter becomes the sub-agent system prompt.
Again, this is a strong separation of concerns. The parent agent sees a concise tool contract, while the child agent receives richer operating instructions.
Finally the code
Below a representative code snippet that show how wires two skill-based sub-agents into a parent agent:
var subAgentMarketplace = SkilledReactSubAgent.builder()
.chatModel(chatModel)
.tools(Marketplace.tools())
.build(compileConfig,
SkillSource.of(Paths.get("skills/agent-marketplace/")));
var subAgentPayment = SkilledReactSubAgent.builder()
.chatModel(chatModel)
.tools(Payment.tools())
.build(compileConfig,
SkillSource.of(Paths.get("skills/agent-payment/")));
var purchaseAssistantAgent = AgentExecutorEx.builder()
.chatModel(chatModel)
.tool(subAgentMarketplace)
.tool(subAgentPayment)
.build(compileConfig);
var input = """
search for product 'X'.
If found proceed to payment with IBAN US82WEST1234567890123456
to purchase it
""";
var result = purchaseAssistantAgent.invoke(
GraphInput.args( Map.of("messages", new UserMessage(input) )), runnableConfig);
This composition is interesting because the purchase agent (the parent) does not need detailed knowledge of:
- how product lookup works
- how payment submission works
- when IBAN retrieval is required
Those rules are delegated to the sub agents themselves.
That is a simple but good example of behavioral encapsulation. The parent agent only decides to involve marketplace agent to retrieve product and after that to involve payment agent to purchase.
This is a very basic but representative example, it is useful because it shows the intended layering:
- the user gives a single business request
- the parent agent decomposes the work
- specialized sub-agents execute their own logic
- the final answer comes back through the normal tool-response path
Interesting note that each sub agent, potentially, can relies on different LLM chat model so we can further optimize overall agent execution process
Below a more detailed componet diagram generated by LangGraph4j itself.
diagram
From this diagram it is quite clear that the sub agents are nothing but sub-graphs
Design Advantages
This approach has several practical advantages.
- Reuse Existing Agent Patterns
There is no need to invent a separate orchestration protocol for sub-agents. A sub-agent is exposed as a tool, so the parent agent can use standard ReAct behavior without extra prompting complexity.
- Better Modularity
Each skill owns:
- its tool-facing identity
- its internal instructions
- its allowed tool boundary
That makes the system easier to evolve than a single monolithic agent prompt.
- Smaller and Cleaner Context
The child agent receives only what it needs. This reduces token usage and lowers the risk that unrelated instructions distort tool choice or task execution.
- Safer Capability Scoping
By filtering tools from allowed-tools, the framework prevents a child agent from accidentally seeing tools outside its intended domain.
- Better Reusability
A skill can be packaged, versioned, and reused across different parent agents. The same marketplace or payment skill can participate in many workflows as long as the tool contract remains stable.
Tradeoffs and Implementation Considerations
This pattern is strong, but it is not free of tradeoffs.
- The Parent Must Summarize Well
Because the child receives a single context field, the parent agent needs to pass the relevant facts clearly. If critical information is omitted, the child may need extra recovery steps or may fail to act.
- Tool Descriptions Matter More
Since the parent sees the child as a tool, the name and description fields in the skill front matter become part of the routing surface for the LLM. Weak metadata will reduce invocation quality.
- Prompt Boundaries Need Discipline
The skill body is effectively the child system prompt. If it is vague, contradictory, or overloaded, the benefits of modularity disappear. Skills need to stay focused.
- Observability Is Important
Nested agents can make execution harder to inspect if tracing is weak. LangGraph4j's graph structure and step streaming help here, but production systems should still invest in logging and traceability.
Why LangGraph4j Fits This Well
LangGraph4j is a good fit for this pattern because it already models agent workflows as explicit graphs and integrates naturally with Spring AI tool abstractions.
That matters for two reasons:
- the sub-agent is not just prompt composition; it is a compiled graph with state and execution hooks
- the parent integration remains ergonomic because Spring AI already treats capabilities as tools
-
LangGraph4j support interruptions in subgraph enabling Human In The Loop also when involving sub agents
So the implementation is not forcing two incompatible ideas together. It is aligning:
- LangGraph4j graph execution
- Spring AI tool calling
- markdown-defined skills
into a single reusable agent-building pattern.
Conclusion
Turning a skill into a sub-agent is a small change with a large impact.
It lets us:
- preserve the strengths of the ReAct loop
- delegate specialized behavior cleanly
- reduce context size
- constrain tool access per domain
- build multi-agent systems out of reusable skill modules
The idea is implemented in a compact and pragmatic way: a SKILL.md file becomes the source of both the sub-agent prompt and the tool contract exposed to the parent agent.
For Java teams building agentic applications with Spring AI and LangGraph4j, this is a practical pattern for moving from a single large agent toward a modular multi-agent design without abandoning the tool semantics that current LLMs already handle well.
The implementation is in progress on release 1.9-SNAPSHOT in develop branch of LangGraph4j repository but the first result are very promising.
Hope this could help and encourage usage of LangGraph4j for your next Agentic Workflow. Checkout project, try it and let me know your feedback and... happy AI coding! π
Originally published at https://bsorrentino.github.io on April 28, 2026.