MoonBit version of LangChain core library — type-safe, composable, embeddable AI Agent framework. Depends on mizchi/llm for LLM clients.
Dependencies
MoonBit 版 LangChain 核心库 —— 类型安全、可组合、可嵌入的 AI Agent 框架
| 版本 | 功能 |
|---|---|
| V0.2-1 | LLMChain::with_output_parser + invoke_and_parse —— 输出解析接入 |
| V0.2-2 | LLMChain::invoke_stream —— 流式输出回调 |
| V0.2-3 | RunnableWrapper::pipe / map + LLMChain::as_runnable —— LCEL 式组合 |
| V0.2-4 | SummaryMemory —— 周期性 LLM 摘要长对话 |
| V0.2-5 | AgentExecutor::invoke_stream —— Agent 流式输出 |
| V0.3-1 | AgentExecutor::with_output_parser + invoke_and_parse —— Agent 输出解析 |
| V0.3-2 | SequentialChain[T] —— 多链编排 |
你的 MoonBit 应用
│
┌─────┴─────┐
│ moon-agent │ ← 本库(12 个子包,109 个测试)
└─────┬─────┘
│
┌─────┬─────┬─────┼─────┬─────┬─────┬─────┐
│ │ │ │ │ │ │ │
core prompts parsers memory tools chains agents
│ │ │ │ │ │ │
└─────┴─────┴─────┴──┬──┴─────┴─────┘
│
config / observability / mcp / rag
│
mizchi/llm ← LLM 客户端底层(Provider、流式、tool_call)
│
OpenAI / Anthropic / ...moon add weopqrst/agent@0.5.0import {
"mizchi/llm@0.3.1",
"weopqrst/agent@0.5.0",
}OPENAI_API_KEY=sk-...
OPENAI_BASE_URL=https://api.deepseek.com
OPENAI_MODEL=deepseek-chat{
"api_key": "sk-...",
"base_url": "https://api.deepseek.com",
"model": "deepseek-chat",
"max_tokens": 4096,
"system_prompt": ""
}moon run cmd/chat --target js=== moon-agent chat v0.5.0 ===
Endpoint: https://api.deepseek.com | Model: deepseek-chat
Type /help for commands, /exit to quit
You: 15 * 23 + 100 等于多少?
Agent:
[→ calling tool: calculator] input: {"expression":"15*23+100"}
[← calculator result] 445
445
Tokens: in=128 out=24 total=152 | Est. cost: $0.000| 命令 | 功能 |
|---|---|
| /exit, /quit | 退出 |
| /help | 查看命令 |
| /tools | 列出内置工具 |
| /clear | 清除对话记忆 |
| /usage | 查看 Token 用量和费用 |
| /errors | 查看错误日志 |
///|
fn main {
let api_key = @env.get_env_var("OPENAI_API_KEY")
match api_key {
Some(key) => {
let prompt = @prompts.ChatPromptTemplate::new()
|> @prompts.ChatPromptTemplate::with_system(
"You are a helpful assistant.",
)
|> @prompts.ChatPromptTemplate::with_user(
"What is {topic}? Answer in one sentence.",
)
let model = @openai.OpenAIProvider::new(key)
let provider = @llm.BoxedProvider::new(model)
let chain = @chains.LLMChain::new(provider, prompt)
let vars : Map[String, String] = Map([])
vars["topic"] = "MoonBit"
let answer = chain.invoke(vars)
println(answer)
}
None => println("Please set OPENAI_API_KEY environment variable.")
}
}let chain = @chains.LLMChain::new(provider, prompt)
|> @chains.LLMChain::with_memory(@memory.BufferMemory::new())
chain.invoke({ "input": "我叫张三" })
let answer = chain.invoke({ "input": "我叫什么名字?" }) // → "你叫张三"///|
let chain = @chains.LLMChain::new(provider, prompt).as_runnable()
///|
let post = @core.RunnableWrapper::new(fn(s : String) -> String {
"Answer length: " + s.length().to_string()
})
///|
let composed = chain.pipe(post)
// 调用 LLM → 取结果长度,一步完成let registry = @llm_tools.ToolRegistry::new()
@tools.register_into(registry, MyWeatherTool::new(api_key))
let executor = @agents.AgentExecutor::new(provider, registry)
|> @agents.AgentExecutor::with_memory(@memory.BufferMemory::new())
|> @agents.AgentExecutor::with_max_steps(5)
let result = executor.invoke("帮我查一下北京的天气")let chain = @chains.LLMChain::new(provider, prompt)
chain.invoke_stream(vars, fn(delta) {
print(delta) // 实时逐字输出
})| 包 | 文件 | 说明 |
|---|---|---|
| core | core.mbt | RunnableWrapper[I,O] 可组合单元 + pipe/map + SequentialChain[T] + RouterChain |
| prompts | template.mbt, chat_prompt.mbt | PromptTemplate({var} 插值)+ ChatPromptTemplate(多角色有序消息) |
| parsers | parser.mbt, boxed_parser.mbt | OutputParser trait + JsonOutputParser + BoxedOutputParser |
| memory | memory.mbt, buffer_memory.mbt, summary_memory.mbt, boxed_memory.mbt | Memory trait + BufferMemory + BufferWindowMemory + SummaryMemory + BoxedMemory |
| tools | tool.mbt, calculator.mbt, datetime.mbt, http.mbt, file_read.mbt, file_write.mbt, shell.mbt, schema.mbt, tool_guard.mbt, tool_middleware.mbt, retrieval_tool.mbt | Tool trait + 6 个内置工具 + 中间件 + RetrievalTool |
| chains | llm_chain.mbt | LLMChain —— prompt + provider + memory + output_parser + 流式 |
| agents | agent_executor.mbt | AgentExecutor —— ReAct Agent 循环 + memory + output_parser + 流式 |
| cache | cache.mbt, boxed.mbt | LLMCache trait + InMemoryCache + BoxedCache —— 响应缓存 |
| async | async.mbt, async_native.mbt | collect_many 并发 LLM 调用(JS 真并发 / 非 JS 串行回退) |
| config | config.mbt | ChatConfig —— .env / config.json / env vars 统一加载 |
| observability | observability.mbt | UsageTracker + CallTrace + TimingTracker + ErrorLogger |
| mcp | mcp_types.mbt, mcp_client.mbt, mcp_server.mbt, mcp_bridge.mbt | MCP 协议双向桥接 |
| rag | loader.mbt, splitter.mbt, store.mbt, embedder.mbt, retriever.mbt, boxed.mbt | Document + MarkdownLoader + RecursiveCharacterTextSplitter + VectorStore + Embedder + Retriever |
| cmd/chat | main.mbt | 交互式 REPL(多轮对话、工具调用可视化) |
| examples/quickstart | main.mbt | 最小 LLMChain 示例 |
| examples/react_agent | main.mbt | 自定义 Tool + ReAct Agent 示例 |
| 测试文件 | 测试数 | 覆盖内容 |
|---|---|---|
| prompts/template_wbtest.mbt | 6 | render / render_one / variables / ChatPromptTemplate 顺序 |
| memory/buffer_memory_wbtest.mbt | 5 | BufferMemory 存取/clear / BufferWindowMemory 窗口/副本 |
| memory/summary_memory_wbtest.mbt | 5 | 摘要触发条件/load_messages/clear/保留最近消息 |
| parsers/parser_wbtest.mbt | 7 | strip_code_fence / JsonOutputParser 含/不含围栏 / CRLF |
| tools/tool_wbtest.mbt | 19 | CalculatorTool/DateTimeTool/ToolGuard/ToolMiddleware |
| chains/llm_chain_wbtest.mbt | 7 | invoke/parse/stream/无parser/无效JSON/向后兼容 |
| agents/agent_executor_wbtest.mbt | 7 | invoke/stream/parse/无parser/invoke_tracked(3个) |
| core/core_wbtest.mbt | 11 | pipe/map/SequentialChain/与wrapper组合 |
| observability/observability_wbtest.mbt | 16 | UsageTracker/CallTrace/TimingTracker/ErrorLogger |
| rag/splitter_wbtest.mbt | 10 | RecursiveCharacterTextSplitter/MarkdownLoader/VectorStore/MMR |
| cache/cache_wbtest.mbt | 9 | InMemoryCache 存取/命中统计/上限/清空/key 生成 |
| async/async_wbtest.mbt | 1 | collect_many 空批次边界 |
moon update # 更新 registry 索引
moon fmt --check # 格式检查
moon build --target js # 构建 JS 目标
moon build --target wasm-gc # 构建 wasm-gc 目标
moon test --target js # 运行测试
moon info # 更新生成接口文件| Version | Feature |
|---|---|
| V0.2-1 | LLMChain::with_output_parser + invoke_and_parse — output parsing integration |
| V0.2-2 | LLMChain::invoke_stream — streaming output callback |
| V0.2-3 | RunnableWrapper::pipe / map + LLMChain::as_runnable — LCEL composition |
| V0.2-4 | SummaryMemory — periodic LLM summarization |
| V0.2-5 | AgentExecutor::invoke_stream — Agent streaming output |
| V0.3-1 | AgentExecutor::with_output_parser + invoke_and_parse — Agent output parsing |
| V0.3-2 | SequentialChain[T] — multi-chain orchestration |
Your MoonBit Application
│
┌─────┴─────┐
│ moon-agent │ ← This library (12 sub-packages, 109 tests)
└─────┬─────┘
│
┌─────┬─────┬─────┼─────┬─────┬─────┬─────┐
│ │ │ │ │ │ │ │
core prompts parsers memory tools chains agents
│ │ │ │ │ │ │
└─────┴─────┴─────┴──┬──┴─────┴─────┘
│
config / observability / mcp / rag
│
mizchi/llm ← LLM client (Provider, streaming, tool_call)
│
OpenAI / Anthropic / ...moon add weopqrst/agent@0.5.0import {
"mizchi/llm@0.3.1",
"weopqrst/agent@0.5.0",
}moon run cmd/chat --target js=== moon-agent chat v0.5.0 ===
Endpoint: https://api.deepseek.com | Model: deepseek-chat
Type /help for commands, /exit to quit
You: What is 15 * 23 + 100?
Agent:
[→ calling tool: calculator] input: {"expression":"15*23+100"}
[← calculator result] 445
445
Tokens: in=128 out=24 total=152 | Est. cost: $0.000| Command | Action |
|---|---|
| /exit, /quit | Exit |
| /help | Show commands |
| /tools | List built-in tools |
| /clear | Clear conversation memory |
| /usage | Show token usage & cost |
| /errors | Show error log |
///|
fn main {
let api_key = @env.get_env_var("OPENAI_API_KEY")
match api_key {
Some(key) => {
let prompt = @prompts.ChatPromptTemplate::new()
|> @prompts.ChatPromptTemplate::with_system(
"You are a helpful assistant.",
)
|> @prompts.ChatPromptTemplate::with_user(
"What is {topic}? Answer in one sentence.",
)
let model = @openai.OpenAIProvider::new(key)
let provider = @llm.BoxedProvider::new(model)
let chain = @chains.LLMChain::new(provider, prompt)
let vars : Map[String, String] = Map([])
vars["topic"] = "MoonBit"
let answer = chain.invoke(vars)
println(answer)
}
None => println("Please set OPENAI_API_KEY environment variable.")
}
}let chain = @chains.LLMChain::new(provider, prompt)
|> @chains.LLMChain::with_memory(@memory.BufferMemory::new())
chain.invoke({ "input": "My name is John" })
let answer = chain.invoke({ "input": "What's my name?" }) // → "Your name is John"///|
let chain = @chains.LLMChain::new(provider, prompt).as_runnable()
///|
let post = @core.RunnableWrapper::new(fn(s : String) -> String {
"Answer length: " + s.length().to_string()
})
///|
let composed = chain.pipe(post)
// Calls LLM → gets result length, in one steplet registry = @llm_tools.ToolRegistry::new()
@tools.register_into(registry, MyWeatherTool::new(api_key))
let executor = @agents.AgentExecutor::new(provider, registry)
|> @agents.AgentExecutor::with_memory(@memory.BufferMemory::new())
|> @agents.AgentExecutor::with_max_steps(5)
let result = executor.invoke("What's the weather in Beijing?")let chain = @chains.LLMChain::new(provider, prompt)
chain.invoke_stream(vars, fn(delta) {
print(delta) // real-time character-by-character output
})| Package | Files | Description |
|---|---|---|
| core | core.mbt | RunnableWrapper[I,O] composable unit + pipe/map + SequentialChain[T] |
| prompts | template.mbt, chat_prompt.mbt | PromptTemplate ({var} interpolation) + ChatPromptTemplate (multi-role ordered messages) |
| parsers | parser.mbt, boxed_parser.mbt | OutputParser trait + JsonOutputParser + BoxedOutputParser |
| memory | memory.mbt, buffer_memory.mbt, summary_memory.mbt, boxed_memory.mbt | Memory trait + BufferMemory + BufferWindowMemory + SummaryMemory + BoxedMemory |
| tools | tool.mbt + 10 built-in tool files | Tool trait + 6 built-in tools + middleware + RetrievalTool |
| chains | llm_chain.mbt | LLMChain — prompt + provider + memory + output_parser + streaming |
| agents | agent_executor.mbt | AgentExecutor — ReAct Agent loop + memory + output_parser + streaming |
| cache | cache.mbt, boxed.mbt | LLMCache trait + InMemoryCache + BoxedCache — response caching |
| async | async.mbt, async_native.mbt | collect_many concurrent LLM calls (JS real concurrency / non-JS serial fallback) |
| config | config.mbt | ChatConfig — .env / config.json / env vars unified loading |
| observability | observability.mbt | UsageTracker + CallTrace + TimingTracker + ErrorLogger |
| mcp | 4 files | MCP protocol bidirectional bridge |
| rag | loader.mbt, splitter.mbt, store.mbt, embedder.mbt, retriever.mbt, boxed.mbt | Document + MarkdownLoader + RecursiveCharacterTextSplitter + VectorStore + Embedder + Retriever |
| cmd/chat | main.mbt | Interactive REPL (multi-turn, tool visualization) |
| examples/quickstart | main.mbt | Minimal LLMChain example |
| examples/react_agent | main.mbt | Custom Tool + ReAct Agent example |
| Test File | Tests | Coverage |
|---|---|---|
| prompts/template_wbtest.mbt | 6 | render / render_one / variables / ChatPromptTemplate ordering |
| memory/buffer_memory_wbtest.mbt | 5 | BufferMemory save/load/clear / BufferWindowMemory window/copy |
| memory/summary_memory_wbtest.mbt | 5 | Summary trigger conditions / load_messages / clear / recent message preservation |
| parsers/parser_wbtest.mbt | 7 | strip_code_fence / JsonOutputParser with/without fence / CRLF |
| tools/tool_wbtest.mbt | 19 | CalculatorTool / DateTimeTool / ToolGuard / ToolMiddleware |
| chains/llm_chain_wbtest.mbt | 7 | invoke / parse / stream / no parser / invalid JSON / backward compat |
| agents/agent_executor_wbtest.mbt | 7 | invoke / stream / parse / no parser / invoke_tracked (3) |
| core/core_wbtest.mbt | 11 | pipe / map / SequentialChain / wrapper composition |
| observability/observability_wbtest.mbt | 16 | UsageTracker / CallTrace / TimingTracker / ErrorLogger |
| rag/splitter_wbtest.mbt | 10 | RecursiveCharacterTextSplitter / MarkdownLoader / VectorStore / MMR |
| cache/cache_wbtest.mbt | 9 | InMemoryCache save/load / hit stats / limit / clear / key generation |
| async/async_wbtest.mbt | 1 | collect_many empty-batch boundary |
let version : Stringlet prompt = @prompts.ChatPromptTemplate::new()
|> @prompts.ChatPromptTemplate::with_system("You are a helpful assistant.")
|> @prompts.ChatPromptTemplate::with_user("What is {topic}?")
let chain = @chains.LLMChain::new(provider, prompt)
let vars : Map[String, String] = Map([])
vars["topic"] = "MoonBit"
let result = chain.invoke(vars)MoonBit version of LangChain core library — type-safe, composable, embeddable AI Agent framework. Depends on mizchi/llm for LLM clients.
Dependencies