How to Write LangGraph-Based Agents that Utilize Skill Containers in DimOS
DimOS provides a LangGraph-based Agent that automatically converts methods decorated with @skill into LangChain tools, enabling LLM-driven execution of robot capabilities through a compiled state graph.
The dimensionalOS/dimos repository ships with a powerful framework for building LangGraph-based agents that utilize skill containers. By decorating methods with @skill and inheriting from the base Module class, developers can expose robot capabilities as LLM-callable tools without manual plumbing.
Understanding Skill Containers and the @skill Decorator
Skill containers are standard DimOS modules that expose public methods decorated with @skill. The decorator, defined in dimos/agents/annotation.py, marks methods as both RPC-callable and LLM-exposed tools.
Key Requirements for Skill Methods
Every skill method must include:
- A descriptive docstring (used as the tool description)
- Type-annotated parameters (used to build the JSON schema)
Example Skill Container Implementation
from dimos.agents.annotation import skill
from dimos.core.core import rpc
from dimos.core.module import Module
class CalculatorSkill(Module):
@rpc
def start(self) -> None:
super().start()
@skill
def add(self, x: float, y: float) -> str:
"""Return the sum of x and y."""
return str(x + y)
calculator = CalculatorSkill.blueprint
Building LangGraph-Based Agents with autoconnect
The Agent class in dimos/agents/agent.py serves as the LangGraph runner. It discovers skills from loaded modules, converts them to LangChain tools, and compiles a state graph for LLM interaction.
Blueprint Composition
Use the autoconnect helper from dimos/core/blueprints.py to wire skill containers to the Agent:
from dimos.agents.agent import Agent
from dimos.core.blueprints import autoconnect
from my_skill import calculator
blueprint = autoconnect(calculator, Agent.blueprint)
if __name__ == "__main__":
blueprint.build().loop()
Tool Discovery and Conversion
When the blueprint builds, Agent.on_system_modules receives RPC clients and calls _get_tools_from_modules. This method:
- Invokes
module.get_skills()to retrieveSkillInfoobjects (defined indimos/core/module.py) - Transforms each skill using
_skill_to_toolinto a LangChainStructuredTool - Passes the tool list to
langchain.agents.create_agentto generate a CompiledStateGraph
Runtime Architecture and Message Flow
Once running, the Agent manages a continuous loop between human input and LLM execution:
- Input Handling: Human messages arrive via the
human_inputstream and are queued asHumanMessageobjects - Graph Execution: The Agent thread calls
state_graph.stream({"messages": history}, stream_mode="updates") - Tool Invocation: When the LLM selects a tool, the wrapped RPC call executes the skill in its original module via
RpcCall - Output Publishing: Results (including images or audio via
agent_encode()) append to message history and publish to theagentoutput stream
The Agent also exposes an agent_idle boolean for monitoring execution state.
Remote Access via MCP Server
For external LLM agents, dimos.agents.mcp.mcp_server.McpServer automatically exposes all @skill tools over HTTP. This enables remote agents to invoke DimOS skills without running the in-process LangGraph Agent.
Summary
- Skill containers are
Modulesubclasses with@skilldecorated methods - The Agent automatically discovers skills and converts them to LangChain tools via
_get_tools_from_modulesand_skill_to_tool - Use
autoconnectfromdimos/core/blueprints.pyto compose skill containers with the Agent - The resulting CompiledStateGraph streams messages between the LLM and skills through the internal RPC system
- Skills returning objects with
agent_encode()automatically publish multimedia artefacts to the chat history
Frequently Asked Questions
What is the difference between @rpc and @skill decorators?
The @rpc decorator (from dimos.core.core) marks methods as callable via the internal RPC system. The @skill decorator (from dimos.agents.annotation) extends this by also exposing the method as a LangChain tool for LLM agents. All @skill methods must also be @rpc enabled, but not all RPC methods need to be skills.
How does the Agent handle type annotations for tool schemas?
The Agent uses the type annotations and docstring from each @skill method to construct the tool schema. Specifically, _skill_to_tool in dimos/agents/agent.py inspects the SkillInfo object (created in dimos/core/module.py) which captures the method's signature. This schema is passed to LangChain's StructuredTool to ensure the LLM receives proper JSON schema definitions for arguments.
Can I use skill containers without the LangGraph Agent?
Yes. Skill containers function as standard DimOS modules and can be invoked directly via RPC calls or exposed through the MCP server (dimos/agents/mcp/mcp_server.py). The MCP server automatically discovers all @skill methods and serves them over HTTP, allowing external LLM agents to invoke DimOS capabilities without instantiating the in-process LangGraph-based Agent.
What happens if a skill returns complex data like images?
Skills returning objects that implement agent_encode() (such as images or audio) automatically have their outputs processed by the Agent's _append_image_to_history method (in dimos/agents/agent.py). The encoded artefacts are appended to the message history and published to the agent output stream, allowing the LLM to receive multimodal context in subsequent turns.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →