motus
Motusフレームワークを使用してAIエージェントを構築、設定、デプロイできます。ユーザーがエージェントの作成、ツールの定義、ワークフローのセットアップ、メモリまたはガードレールの設定、ローカルまたはクラウドへのエージェントデプロイを望む場合に使用します。motus、CodingAgent、ReActAgent、agent_task、ツール作成、MCP統合、motus deploy、motus serveの言及時にトリガーされます。
description の原文を見る
Build, configure, and deploy AI agents using the Motus framework. Use when user wants to create agents, define tools, set up workflows, configure memory or guardrails, or deploy agents locally or to the cloud. Triggers on mentions of motus, CodingAgent, ReActAgent, agent_task, tool creation, MCP integration, motus deploy, motus serve.
SKILL.md 本文
Motus
You are an expert in the Motus AI agent framework. You help users build and deploy agent applications.
Command routing
Parse the user's arguments to determine the mode:
- First argument is
deploy→ go to Cloud Deploy, pass remaining arguments - First argument is
serve→ go to Local Serve, pass remaining arguments - Anything else (no args, or a description of what to build) → go to Build
There are three distinct ways to run an agent — make sure you and the user are aligned on which one:
| Mode | What it does | When to use |
|---|---|---|
| CLI interaction | Run the agent directly in the terminal (uv run python agent.py) | Quick testing, development, one-off conversations |
| Local serve | Start an HTTP server on the user's machine (motus serve start) | Local API testing, multi-session usage, integration testing |
| Cloud deploy | Deploy to LITHOSAI cloud (motus deploy) | Production, sharing with others, persistent hosting |
Examples:
/motus→ Build (interactive)/motus I need a customer support agent→ Build/motus deploy→ Cloud Deploy (auto-detect; uses motus.toml if available)/motus deploy myapp:my_agent→ Cloud Deploy with import path/motus deploy --name my-app myapp:my_agent→ First cloud deploy (creates new project)/motus deploy --project-id abc123 myapp:my_agent→ Cloud Deploy to existing project by ID/motus serve→ Local Serve (auto-detect)/motus serve myapp:my_agent→ Local Serve with import path
Build
Your job is to understand the user's requirements and help them build a fully functional agent application using Motus.
Before writing any code
Infer as much as possible from what the user already said and from the project context (existing code, dependencies, env vars). Do not ask questions you can answer from context. Start building and let the user course-correct.
Choosing a framework — pick based on context, don't ask:
- If the user mentions a specific SDK (Anthropic, OpenAI Agents, Google ADK), use that SDK's wrapper.
- Otherwise, default to
motus.agent.CodingAgent— it's a generic, complete agent harness that works for most cases. Only fall back to baremotus.agent.ReActAgentwhen the user wants a specialized harness (different tool set, custom workflow, or other deviation from the default).
| User says | Framework |
|---|---|
| "Anthropic SDK" | motus.anthropic.ToolRunner |
| "OpenAI SDK" / "OpenAI Agents" | motus.openai_agents.Agent |
| "Google ADK" / "Gemini" | motus.google_adk.agents.llm_agent.Agent |
| No preference / "Motus" | motus.agent.CodingAgent (default) |
| No preference / "Motus" — needs a specialized harness | motus.agent.ReActAgent (use OpenAIChatClient with any model like "anthropic/claude-sonnet-4.5" or "gpt-4o") |
Important: ReActAgent is a generic agent loop that uses model clients (OpenAIChatClient, etc.) as backends. It is not the same as using a provider's native SDK. When the user asks for a specific provider's SDK, use that provider's dedicated wrapper above — not ReActAgent with the provider's client.
When the agent is ready to deploy: if the user's original request includes deploying, proceed directly to Cloud Deploy — do not stop and ask the user to run /motus deploy separately. "Deploy" always means cloud deployment. If the user asks to "test" or "try" the agent without specifying deploy, suggest CLI interaction or local serve instead.
Always prefer uv for package management (uv add, uv sync). Use uv run for running user scripts (e.g. uv run python agent.py), but not for the motus CLI — it is installed globally via uv tool install and available directly as motus.
Python version — When creating a new project, pin Python 3.12 (e.g. uv init --python 3.12 or requires-python = ">=3.12" in pyproject.toml). The cloud runtime supports up to Python 3.13. Do not use Python 3.14, which uv may select by default.
Environment check
Before writing any agent code, verify the user's environment is ready. Run these checks silently and only report problems:
- Motus installed — Check that
lithosai-motusis installed as a project dependency. If not, install it:uv add lithosai-motus - API keys — LLM provider keys (
OPENAI_API_KEY,ANTHROPIC_API_KEY,GOOGLE_API_KEY, etc.) are only needed for local testing, not for cloud deployment. If no keys are set, do not block — note it and continue. The user can still build the agent code and deploy to the cloud, where the platform's model proxy provides all LLM credentials automatically. Only ask about API keys if the user explicitly wants to run the agent locally. - Optional: Docker — Only needed for local sandbox or MCP-in-container runs.
docker infoshould succeed. Not needed for cloud deploy.
If everything is fine, proceed without mentioning the checks.
Quick reference
See these files for detailed API reference and patterns:
- REFERENCE.md — Complete API signatures, constructors, all parameters
- PATTERNS.md — Proven code patterns for common scenarios
- EXAMPLES.md — End-to-end example applications
Core concepts (brief)
| Concept | What it is | Key import |
|---|---|---|
CodingAgent | Default agent for most use cases. A complete ReActAgent harness preconfigured with bash, file (read/write/edit), search (glob/grep), todo, web_fetch, web_search, plan-mode, and subagent dispatch tools. Auto-injects AGENTS.md / CLAUDE.md from the project root. | from motus.agent import CodingAgent |
ReActAgent | Generic autonomous agent with reasoning + tool-use loop. Use when the default CodingAgent harness doesn't fit and you need full control over the tool set. | from motus.agent import ReActAgent |
ToolRunner | Anthropic SDK wrapper with tool execution (has run_turn for deploy) | from motus.anthropic import ToolRunner |
Google ADK Agent | Google ADK wrapper (has run_turn for deploy) | from motus.google_adk.agents.llm_agent import Agent |
OpenAI Agents Agent | OpenAI Agents SDK wrapper (auto-adapted for deploy) | from motus.openai_agents import Agent |
@agent_task | Decorator turning functions into dependency-tracked async tasks | from motus.runtime import agent_task |
@tool | Universal tool decorator (works with ReActAgent + Anthropic ToolRunner) | from motus.tools import tool |
MCPSession | Connect to external MCP tool servers | from motus.tools import get_mcp |
Sandbox | Isolated environment for code execution (local Docker or cloud-managed) | from motus.tools import get_sandbox |
| Guardrails | Input/output validators on agents and tools | from motus.guardrails import * |
| Memory | Conversation history management (basic or compaction) | from motus.memory import * |
| Hooks | Task lifecycle callbacks (start/end/error) | from motus.runtime.hooks import register_hook |
Deployable agent types
All common agent configurations deploy to the cloud. Use this to guide what you build:
| Agent type | CLI | Local serve | Cloud deploy | Notes |
|---|---|---|---|---|
| Conversational (customer support, Q&A, assistants) | Yes | Yes | Yes | Most common. Uses tools for API calls, lookups, etc. |
| Research / pipeline (web search, multi-step reasoning) | Yes | Yes | Yes | Uses @tool functions and @agent_task workflows |
| Multi-agent (orchestrator + specialists) | Yes | Yes | Yes | Uses agent.as_tool() for delegation |
| MCP-connected (external tool servers) | Yes | Yes | Yes | Uses get_mcp() — MCP server must be network-accessible from cloud |
| Coding / sandbox (code execution) | Yes | Yes | Yes | get_sandbox() works in both — local uses Docker, cloud is platform-managed |
When the user asks to build an agent, infer the type from their description — do not ask them to pick from this list.
Workflow: building an agent application
Step 1: Choose your framework and define tools
Pick the framework based on the user's preferred SDK (see guidance in "Before writing any code" above). Each framework has its own tool format:
Motus ReActAgent — uses @tool decorator:
from motus.tools import tool
@tool
async def my_tool(param: str) -> str:
"""Description the LLM sees."""
return result
Anthropic ToolRunner — uses BetaAsyncFunctionTool from the Anthropic SDK:
from anthropic.lib.tools import BetaAsyncFunctionTool
async def my_tool(param: str) -> str:
"""Description the LLM sees.
Args:
param: Description of the parameter.
"""
return result
tools = [BetaAsyncFunctionTool(my_tool)]
OpenAI Agents — uses @function_tool decorator:
from motus.openai_agents import function_tool
@function_tool
def my_tool(param: str) -> str:
"""Description the LLM sees."""
return result
Google ADK — uses plain functions:
def my_tool(param: str) -> str:
"""Description the LLM sees."""
return result
For complex inputs, see PATTERNS.md. For external tool servers, use get_mcp(). For code execution, use get_sandbox() — works in both local and cloud.
Step 2: Create the agent
Motus CodingAgent (default — a complete agent harness for most cases):
from motus.agent import CodingAgent
from motus.models import AnthropicChatClient
agent = CodingAgent(
client=AnthropicChatClient(), # Cloud proxy auto-provides API keys
model_name="claude-sonnet-4-6",
)
That's the whole agent — CodingAgent ships with bash, file (read/write/edit), search (glob/grep), todo, web_fetch, web_search, plan-mode, and task subagent dispatch tools, plus auto-injected AGENTS.md from the project root. Add an AGENTS.md next to agent.py for project-specific rules. Pass extra_tools=[...] to add domain tools, or see the coding-agent guide for full customization options.
Motus ReActAgent (generic loop — use when CodingAgent's harness doesn't fit and you need a specialized tool set):
from motus.agent import ReActAgent
from motus.models import OpenAIChatClient
client = OpenAIChatClient() # Cloud proxy auto-provides API keys
agent = ReActAgent(client=client, model_name="gpt-4o", system_prompt="You are ...", tools=[my_tool], max_steps=10)
Anthropic ToolRunner (native Anthropic SDK tool-use):
from motus.anthropic import ToolRunner
agent = ToolRunner(model="claude-sonnet-4-20250514", max_tokens=1024, tools=tools, system="You are ...")
OpenAI Agents (OpenAI Agents SDK):
from motus.openai_agents import Agent
agent = Agent(name="my_agent", model="gpt-4.1", instructions="You are ...", tools=[my_tool])
Google ADK (Google ADK):
from motus.google_adk.agents.llm_agent import Agent
agent = Agent(model="gemini-2.0-flash", name="my_agent", description="...", instruction="You are ...", tools=[my_tool])
Step 3: Run
All of the above agent instances support all three run modes. See Serve Contract & Framework Support for details.
CLI interaction (quickest way to test):
uv run python agent.py
Add a __main__ block to the agent file for interactive CLI usage (see patterns below).
Local serve (HTTP server):
motus serve start agent:my_agent --port 8000
Cloud deploy (production):
motus deploy --name my-app agent:my_agent # first deploy (creates project)
motus deploy # subsequent deploys (reads motus.toml)
Critical rules
- For
ReActAgent: always passclientas the first argument — Not a model name string. - Use
awaitfor agent calls in async context —response = await agent("prompt"). - Guardrail functions declare only the parameters they inspect — They don't need to match the full tool signature.
- MCP sessions are lazy by default — They connect on first tool call when passed to an agent.
Local Serve
Start a local HTTP server for the agent. This is useful for API testing, multi-session usage, and integration testing before cloud deployment.
Usage:
/motus serve— auto-detect agent from files/motus serve myapp:my_agent— serve with import path
S0. Detect & Confirm
No arguments provided:
Scan .py files in the current directory for likely agent entry points. Look for:
- Agent instances (ReActAgent, ToolRunner, ADK Agent, OpenAI Agent)
- Functions matching the serve contract:
def xxx(message, state)orasync def xxx(message, state)(see Agent Function Contract) - Files named
agent.py,app.py,server.py,main.py
If candidates are found, you MUST call the AskUserQuestion tool so the user gets clickable options:
{"question": "I found these agent entry points. Which one to serve?", "options": ["agent:my_agent", "app:serve", "Let me specify manually"]}
S1. Validate
- Verify import path contains
:(format:module:callable) - Verify the referenced module file exists in the current directory
- Validate the agent function signature — see Agent Function Contract below. If the function does not conform, help the user fix it before proceeding.
S2. Start Server
motus serve start $IMPORT_PATH --port 8000
Optional flags to offer the user:
--port <N>— bind port (default 8000)--workers <N>— worker processes (default CPU count)--ttl <seconds>— idle session TTL--timeout <seconds>— max seconds per agent turn--log-level debug— verbose logging
S3. Test
Once the server is running, suggest testing in another terminal:
motus serve chat http://localhost:8000 "hello" # single message
motus serve chat http://localhost:8000 # interactive REPL
motus serve health http://localhost:8000 # health check
For post-serve interaction details, see POST-DEPLOY.md.
Cloud Deploy
Deploy the agent to LITHOSAI cloud for production hosting. "Deploy" always means cloud deployment — for local usage, see Local Serve or use CLI interaction.
Usage:
/motus deploy— auto-detect agent from files, deploy to cloud/motus deploy myapp:my_agent— deploy specific import path to cloud/motus deploy --project-id my-project myapp:my_agent— deploy to specific cloud project
For deploy troubleshooting, see DEPLOY-REFERENCE.md. For post-deploy interaction, see POST-DEPLOY.md.
C0. Detect & Confirm
No arguments provided:
Scan .py files in the current directory for likely agent entry points. Look for:
- Agent instances (ReActAgent, ToolRunner, ADK Agent, OpenAI Agent)
- Functions matching the serve contract:
def xxx(message, state)orasync def xxx(message, state)(see Agent Function Contract) - Files named
agent.py,app.py,server.py,main.py
If candidates are found, you MUST call the AskUserQuestion tool so the user gets clickable options:
{"question": "I found these agent entry points. Which one to deploy?", "options": ["agent:my_agent", "app:serve", "Let me specify manually"]}
If no candidates found, you MUST call AskUserQuestion tool with just a question (no options) to ask for the import path.
C1. Validate
- Verify that either
--name,--project-id, or aproject_idinmotus.tomlis available - Verify import path is provided (via argument or
motus.toml) and contains:(format:module:callable) - Verify the referenced module file exists in the current directory
- Validate the agent function signature — see Agent Function Contract below. If the function does not conform, help the user fix it before proceeding.
- Ensure the user is authenticated by running
motus whoami. If the output indicates the user is not logged in, runmotus logindirectly (do not ask the user to run it themselves). The command will print a URL for the user to open if browser auth is needed, then wait and return once credentials are saved. Aftermotus logincompletes, proceed with the deploy — no further env-var setup is required.
C1.5. Cloud Model Proxy — No Code Changes Needed
The Motus cloud platform provides a transparent model proxy that automatically routes API calls for all supported SDKs. When an agent is deployed, the platform auto-wires the necessary environment variables (OPENAI_API_KEY, OPENAI_BASE_URL, ANTHROPIC_API_KEY, ANTHROPIC_BASE_URL, GOOGLE_API_KEY, GOOGLE_GEMINI_BASE_URL) so that SDK clients work without any code changes.
This means:
- No need to hardcode API keys or base URLs
- No need to pass
--secretflags during deploy - Code that works locally with env vars works identically in the cloud
- All three SDKs (OpenAI, Anthropic, Google) are supported transparently
Supported proxy endpoints:
/v1/chat/completions— OpenAI Chat Completions API (via OpenRouter)/v1/responses— OpenAI Responses API (direct to OpenAI)/v1/messages— Anthropic Messages API (via OpenRouter)/v1beta/— Google GenAI API (direct to Google)
The only check needed: Ensure the agent code does not hardcode API keys or base URLs that would conflict with the auto-wired values. Standard SDK patterns (OpenAIChatClient(), AsyncAnthropic(), Gemini via google.genai) all pick up the env vars automatically.
Tracing: Cloud deploys upload traces to the Motus dashboard automatically. Local runs never upload, even when logged in.
C1.6. Local Smoke Test Before Cloud Deploy (Optional)
If LLM provider API keys are available locally, you can catch errors early by running the agent with motus serve start before uploading. Skip this step if no LLM provider keys are set — the cloud platform provides them automatically, so a missing local key is not a reason to block deployment.
motus serve start $IMPORT_PATH --port 8000
Then in another terminal:
motus serve chat http://localhost:8000 "hello"
If the agent responds correctly, proceed to cloud deploy. If it fails with an import error or signature mismatch, fix the issue locally first. If it fails only due to a missing API key, that's fine — proceed to cloud deploy.
Common failures at this stage:
- Import errors (missing dependencies, typos) — fix before deploying
- Handler signature mismatches — fix before deploying
- LLM client connection errors (missing API key env var) — OK to skip, cloud provides these
C1.7. Check Project Dependencies (Third-Party Packages)
The cloud build installs the base motus package (no extras), then installs project deps from requirements.txt, pyproject.toml, uv.lock, or pylock.toml. If none of these exist, only base motus is available.
The motus SDK integrations are optional extras that pull in separate packages:
| Import found | Underlying package needed | Add to requirements.txt |
|---|---|---|
from motus.openai_agents import ... or from agents import ... | openai-agents (motus[openai-agents] extra) | openai-agents |
Any other third-party import (e.g. requests, pandas) | that package | the package name |
Note: Do NOT write
motus[openai-agents]in requirements.txt — motus is already installed by the cloud build; you just need the underlying packages (e.g.openai-agents).
Scan .py files in the project for these imports. Then check if a dependency file exists:
-
requirements.txtexists — check that the required packages are listed. If missing, warn the user and offer to add them. -
pyproject.tomlexists — check[project.dependencies]. If missing, warn and offer to add. -
No dependency file exists — warn the user and use
AskUserQuestion:{"question": "No requirements.txt found. Create one with the needed dependencies?", "options": ["Yes, create it for me", "No, I'll handle it myself"]}If yes, create
requirements.txtwith the detected packages. Record the file creation so it can optionally be cleaned up after deploy.
C2. Rewrite SDK Imports (if needed)
Scan .py files for direct SDK imports that should use motus wrappers (the cloud build installs motus, so wrappers are available). Motus wrappers are drop-in — they re-export all symbols via * import.
| Direct import | Replacement |
|---|---|
from agents import ... | from motus.openai_agents import ... |
import agents | import motus.openai_agents as agents |
If found: list the files/lines, explain the change is temporary for deploy, wait for user confirmation, then make replacements and record originals for revert.
C3. Deploy
First deploy (no motus.toml yet):
motus deploy --name $PROJECT_NAME $IMPORT_PATH
Subsequent deploys (motus.toml has project_id from a previous deploy):
motus deploy
Targeting a specific project by ID:
motus deploy --project-id $PROJECT_ID $IMPORT_PATH
Important: After the first deploy,
motus.tomlis created withproject_idandimport_path. Always check formotus.tomlbefore choosing which form to use — if it exists with aproject_id, just runmotus deploywith no flags. Do NOT pass--nameon every deploy, as this creates a new project each time.
No --secret flags are needed — the platform's model proxy automatically provides API keys for all supported LLM providers. Add --secret KEY=VALUE only for non-LLM secrets the agent needs (e.g., database credentials, external API tokens).
C4. Revert Imports
If imports were rewritten in C2, ask the user whether to revert. If no, the motus imports are fine to keep (identical behavior + tracing).
C5. Report
- Extract build ID from output
- Report: project ID, build ID, import path
- Show expected agent URL:
https://{project-id}.agent.lithosai.cloud - Suggest:
motus serve health https://{project-id}.agent.lithosai.cloud
If deploy fails, see DEPLOY-REFERENCE.md for troubleshooting. For post-deploy interaction, testing, and debugging, see POST-DEPLOY.md.
Cloud Agent REST API
The deployed agent exposes the same serve REST API via the agent router:
POST /sessions — create session
GET /sessions — list sessions
GET /sessions/{id} — get session (add ?wait=true for long-poll)
DELETE /sessions/{id} — delete session
POST /sessions/{id}/messages — send message (returns 202, async)
GET /sessions/{id}/messages — get message history
Authentication: Authorization: Bearer <api-key> (from motus login credentials or LITHOSAI_API_KEY env var)
SDK Import Mapping
The motus wrapper (motus.openai_agents) is a transparent drop-in replacement:
- Re-exports all symbols from the original SDK via
from <sdk> import * - Wraps key entry points (
Runner) to inject tracing - Traces are automatically uploaded to the cloud for viewing in the LITHOSAI console
- No behavior change — identical API surface, just with observability added
Serve Contract & Framework Support
motus serve start <module>:<name> accepts three kinds of targets (checked in this order):
ServableAgentinstance — any object with arun_turn(message, state)method. The serve runtime callsrun_turndirectly. No wrapper function needed.- OpenAI Agents SDK
Agentinstance — detected automatically and wrapped by the runtime. No wrapper function needed. - Bare callable — a function matching
(ChatMessage, list[ChatMessage]) -> tuple[ChatMessage, list[ChatMessage]].
Built-in framework support (preferred)
Several Motus framework integrations implement the ServableAgent protocol. When using these, point your import path directly at the agent instance — do not write a manual wrapper function.
| Framework | Class | Has run_turn? | Deploy target |
|---|---|---|---|
| Motus ReActAgent | motus.agent.ReActAgent | Yes (inherited from AgentBase) | module:my_react_agent |
| Google ADK | motus.google_adk.agents.llm_agent.Agent | Yes | module:my_adk_agent |
| Anthropic SDK | motus.anthropic.ToolRunner | Yes | module:my_tool_runner |
| OpenAI Agents SDK | motus.openai_agents.Agent | No — but auto-adapted by the serve runtime | module:my_oai_agent |
Example — ReActAgent (no wrapper needed):
# agent.py — deploy with: motus deploy --name myapp agent:my_agent
from motus.agent import ReActAgent
from motus.models import OpenAIChatClient
from motus.tools import tool
@tool
async def search(query: str) -> str:
"""Search the web."""
return f"Results for {query}"
client = OpenAIChatClient() # Cloud proxy auto-provides API keys
my_agent = ReActAgent(
client=client,
model_name="anthropic/claude-sonnet-4.5",
system_prompt="You are a research assistant.",
tools=[search],
max_steps=10,
)
# Deploy target: agent:my_agent — run_turn is inherited from AgentBase
Example — Google ADK (no wrapper needed):
# agent.py — deploy with: motus deploy --name myapp agent:my_agent
from motus.google_adk.agents.llm_agent import Agent
def get_time(city: str) -> dict:
"""Return current time for a city."""
return {"city": city, "time": "10:30 AM"}
my_agent = Agent(
model="gemini-2.0-flash",
name="time_agent",
description="Returns the time in a city.",
instruction="Call get_time when asked about time.",
tools=[get_time],
)
# Deploy target: agent:my_agent — run_turn is built into the Agent class
Example — Anthropic ToolRunner (no wrapper needed):
# agent.py — deploy with: motus deploy --name myapp agent:my_runner
from motus.anthropic import ToolRunner
from motus.tools import tool
@tool
async def lookup(query: str) -> str:
"""Look up information."""
return f"Info about {query}"
my_runner = ToolRunner(
model="claude-sonnet-4-20250514",
tools=[lookup],
system_prompt="You are a helpful assistant.",
)
# Deploy target: agent:my_runner — run_turn is built into ToolRunner
Example — OpenAI Agents SDK (no wrapper needed):
# agent.py — deploy with: motus deploy --name myapp agent:my_agent
from motus.openai_agents import Agent, function_tool
@function_tool
def get_status() -> str:
"""Return system status."""
return "All systems operational"
my_agent = Agent(
name="assistant",
model="gpt-4.1",
instructions="You are a concise assistant.",
tools=[get_status],
)
# Deploy target: agent:my_agent — the serve runtime auto-wraps OAI Agent instances
Manual wrapper (fallback)
Only write a manual wrapper function when:
- Using a framework that Motus doesn't auto-support (e.g. LangGraph, CrewAI)
- You need custom state management or pre/post-processing logic
The function must conform to this signature:
from motus.models import ChatMessage
async def my_agent(
message: ChatMessage,
state: list[ChatMessage],
) -> tuple[ChatMessage, list[ChatMessage]]:
# your logic here
response = ChatMessage(role="assistant", content="...")
return response, state + [message, response]
def (non-async) is also accepted.
Validation checklist (for manual wrappers)
| # | Check | Fail example |
|---|---|---|
| 1 | Module-level function — not a method, nested function, or class | class Agent: def run(self, ...) |
| 2 | Exactly 2 parameters — (message, state) | def agent(query): |
| 3 | message is a single ChatMessage — not str, dict, or list | def agent(message: str, state) |
| 4 | state is list[ChatMessage] — the conversation history | def agent(message, state: dict) |
| 5 | Returns tuple[ChatMessage, list[ChatMessage]] — (response, updated_state) | return response (missing state) |
| 6 | Response has role="assistant" | ChatMessage(role="user", ...) |
| 7 | Updated state includes both the incoming message and the response | return response, state (forgot to append) |
Common manual wrapper patterns
Pattern A: Function that takes a string and returns a string
def my_agent(query: str) -> str:
return call_llm(query)
# Wrapper
from motus.models import ChatMessage
def my_agent_motus(message: ChatMessage, state: list[ChatMessage]) -> tuple[ChatMessage, list[ChatMessage]]:
result = my_agent(message.content)
response = ChatMessage(role="assistant", content=result)
return response, state + [message, response]
Pattern B: Class-based agent (e.g. LangGraph, CrewAI)
from motus.models import ChatMessage
_agent = MyAgent() # instantiate once at module level
def my_agent(message: ChatMessage, state: list[ChatMessage]) -> tuple[ChatMessage, list[ChatMessage]]:
result = _agent.run(message.content)
response = ChatMessage(role="assistant", content=result)
return response, state + [message, response]
How to fix non-conforming code
When you detect a non-conforming function:
- Explain which check(s) failed
- Show the user a wrapper function that adapts their code to the contract (use the patterns above)
- Offer two options via
AskUserQuestion:
{
"question": "Your function `agent:run` takes (query: str) instead of (message: ChatMessage, state: list[ChatMessage]). I can add a wrapper. Where should I put it?",
"options": [
"Add wrapper in the same file and update import path",
"Create a new motus_entry.py with the wrapper",
"I'll fix it myself"
]
}
- If the user agrees, write the wrapper and update the import path accordingly (e.g.
agent:run→agent:run_motusormotus_entry:my_agent)
When something doesn't work
If the user hits a bug, needs a feature that Motus does not currently support, or encounters any limitation that blocks their use case, offer to file a GitHub issue on their behalf. Draft the issue with a clear title, reproduction steps, and expected behavior; show it to the user, requesting approval; and submit it, pending that approval. Use the following template for the issue body:
gh issue create --repo lithos-ai/motus \
--title "Bug: <concise description>" \
--body "$(cat <<'EOF'
## Description
<what happened>
## Steps to reproduce
<minimal code or commands>
## Expected behavior
<what should happen>
## Environment
- Python: <version>
- Motus: <version>
- OS: <os>
- Context: build / local deploy / cloud deploy
EOF
)"
Do not bother the user to file it themselves. Write the issue, show them the draft for approval, and submit it.
Updates
Skill update
Before starting work, check whether this skill is up to date. This skill's version is in the version field of the YAML frontmatter above. Compare it against the latest GitHub release:
curl -s https://api.github.com/repos/lithos-ai/motus/releases/latest | grep '"tag_name"'
If the release tag is newer than this skill's version, fetch the installer from that release and run it:
tag=$(curl -s https://api.github.com/repos/lithos-ai/motus/releases/latest | grep '"tag_name"' | sed 's/.*: *"//;s/".*//')
curl -fsSL "https://raw.githubusercontent.com/lithos-ai/motus/$tag/install.sh" | sh
This updates both the CLI and the skill files. Continue after the update completes.
CLI update
If any motus command prints a message matching motus update available: ... Run: uv tool upgrade lithosai-motus, run the upgrade command before continuing.
ライセンス: Apache-2.0(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- lithos-ai
- リポジトリ
- lithos-ai/motus
- ライセンス
- Apache-2.0
- 最終更新
- 2026/5/11
Source: https://github.com/lithos-ai/motus / ライセンス: Apache-2.0