关于 Sema
Sema 是一种类 Scheme 的 Lisp,将 LLM Agent 作为语言原语提供,编译为字节码虚拟机并打包为单一二进制文件。面向需要脚本化 LLM 调用的开发者,重试、缓存、预算等通常需要手写的逻辑由运行时承担。
主要功能
- 01提示词、会话和工具作为一等数据类型
- 02内置多家模型提供商的自动配置
- 03缓存、回退链、限流与重试
- 04预算追踪与 OpenTelemetry 自动追踪
- 05内置格式化器、LSP、DAP 与 MCP 服务
适用场景
- 01编写带文件工具的编码 Agent 脚本
- 02从文本中提取结构化数据
- 03在 CLI 中批量执行 LLM 调用并控制成本
MCP 相关
sema mcp 提供 MCP 服务,供 Claude Desktop、Cursor、Claude Code 等 LLM 客户端调用,用于编译、格式化、求值和构建 Sema 代码,并可调用用户通过 deftool 定义的 Lisp 工具。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
别再重写 Agent 循环了。 每个 LLM 脚本都会搭建相同的脚手架——重试、缓存、成本上限、速率限制、工具调度、对话状态。Sema 将这些脚手架变成运行时:你的脚本保持构想本身的简洁,以单个二进制文件发布,而且你的编码 Agent 已经会说这种语言。
Sema 是一种类似 Scheme 的 Lisp,其中提示词是 s 表达式、对话是持久化数据结构,而 LLM 调用只是另一种求值形式——支持 Clojure 风格的关键字(:foo)、映射字面量({:key val})和向量字面量([1 2 3])。
效果一览
一个具备文件工具、安全检查和预算跟踪功能的编码 Agent——约 40 行代码:
;; Define tools the LLM can call
(deftool read-file
"Read a file's contents"
{:path {:type :string :description "File path"}}
(lambda (path)
(if (file/exists? path) (file/read path) "File not found")))
(deftool edit-file
"Replace text in a file"
{:path {:type :string} :old {:type :string} :new {:type :string}}
(lambda (path old new)
(file/write path (string/replace (file/read path) old new))
"Done"))
(deftool run-command
"Run a shell command"
{:command {:type :string :description "Shell command to run"}}
(lambda (command) (:stdout (shell "sh" "-c" command))))
;; Create an agent with tools, system prompt, and spending limit
(defagent coder
{:system (format "You are a coding assistant. Working directory: ~a" (sys/cwd))
:tools [read-file edit-file run-command]
:max-turns 20}) ; no :model → uses the configured default provider
;; Run it — budget is scoped, automatically restored after the block
(llm/with-budget {:max-cost-usd 0.50} (lambda ()
(define result (agent/run coder "Add error handling to src/main.rs"))
(println (:response result))
(println (format "Cost: $~a" (:spent (llm/budget-remaining))))))
主要特性
;; Simple completion
(llm/complete "Explain monads in one sentence")
;; Structured data extraction — returns a map, not a string
(llm/extract
{:vendor {:type :string} :amount {:type :number} :date {:type :string}}
"Bought coffee for $4.50 at Blue Bottle on Jan 15")
;; => {:amount 4.5 :date "2025-01-15" :vendor "Blue Bottle"}
;; Classification
(llm/classify (list :positive :negative :neutral) "This product is amazing!")
;; => :positive
;; Multi-turn conversations as immutable data
(define conv (conversation/new {:model "claude-haiku-4-5-20251001"}))
(define conv (conversation/say conv "The secret number is 7"))
(define conv (conversation/say conv "What's the secret number?"))
(conversation/last-reply conv) ;; => "The secret number is 7."
;; Streaming
(llm/stream "Tell me a story" {:max-tokens 500})
;; Batch — all prompts sent concurrently
(llm/batch (list "Translate 'hello' to French"
"Translate 'hello' to Spanish"
"Translate 'hello' to German"))
;; Vision — extract structured data from images
(llm/extract-from-image
{:text :string :background_color :string}
"assets/logo.png")
;; => {:background_color "white" :text "Sema"}
;; Multi-modal chat — send images in messages
(define img (file/read-bytes "photo.jpg"))
(llm/chat (list (message/with-image :user "Describe this image." img)))
;; Cost tracking
(llm/set-budget 1.00)
(llm/budget-remaining) ;; => {:limit 1.0 :spent 0.05 :remaining 0.95}
;; Response caching — avoid duplicate API calls during development
(llm/with-cache (lambda ()
(llm/complete "Explain monads")))
;; Cassettes — record real responses once, replay them in CI (no keys, no network)
(llm/with-cassette "fixtures/run.jsonl" {:mode :auto} (lambda ()
(llm/complete "Explain monads")))
;; Fallback chains — automatic provider failover
(llm/with-fallback [:anthropic :openai :groq]
(lambda () (llm/complete "Hello")))
;; In-memory vector store for semantic search (RAG)
(vector-store/create "docs")
(vector-store/add "docs" "id" (llm/embed "text") {:source "file.txt"})
(vector-store/search "docs" (llm/embed "query") 5)
;; Cross-encoder reranking — the retrieve-many → rerank-to-a-few RAG move
(llm/rerank "how do I read a file?"
["file/read returns a string" "http/get fetches a URL"]
{:top-k 3})
;; => ({:index 0 :score 0.98 :document "file/read returns a string"} ...)
;; Text chunking for LLM pipelines
(text/chunk long-document {:size 500 :overlap 100})
;; Prompt templates
(prompt/render "Hello {{name}}" {:name "Alice"})
; => "Hello Alice"
;; Persistent key-value store
(kv/open "cache" "cache.json")
(kv/set "cache" "key" {:data "value"})
(kv/get "cache" "key")
支持的提供商
所有提供商都会根据环境变量自动配置——只需设置 API 密钥即可开始使用。
| 提供商 | 聊天 | 流式 | 工具 | 嵌入 | 视觉 |
|---|---|---|---|---|---|
| Anthropic | ✅ | ✅ | ✅ | — | ✅ |
| OpenAI | ✅ | ✅ | ✅ | ✅ | ✅ |
| Google Gemini | ✅ | ✅ | ✅ | — | ✅ |
| Ollama | ✅ | ✅ | ✅ | — | ✅ |
| Groq | ✅ | ✅ | ✅ | — | — |
| xAI | ✅ | ✅ | ✅ | — | — |
| Mistral | ✅ | ✅ | ✅ | — | — |
| Moonshot | ✅ | ✅ | ✅ | — | — |
| Jina | — | — | — | ✅ | — |
| Voyage | — | — | — | ✅ | — |
| Cohere | — | — | — | ✅ | — |
| 任何兼容 OpenAI 的服务 | ✅ | ✅ | ✅ | — | ✅ |
| 自定义(Lisp) | ✅ | — | ✅ | — | — |
它也是一门真正的 Lisp
数百个内置函数、尾调用优化、宏、模块、错误处理——绝非玩具。
;; Closures, higher-order functions, TCO
(define (fibonacci n)
(let loop ((i 0) (a 0) (b 1))
(if (= i n) a (loop (+ i 1) b (+ a b)))))
(fibonacci 50) ;; => 12586269025
;; Full R7RS numeric tower — bignums, exact rationals, complex numbers
(expt 2 100) ;; => 1267650600228229401496703205376
(+ 1/2 1/3) ;; => 5/6
(sqrt -1) ;; => 0+1i
;; Maps, keywords-as-functions, f-strings
(define person {:name "Ada" :age 36 :langs ["Lisp" "Rust"]})
(:name person) ;; => "Ada"
(println f"${(:name person)} knows ${(length (:langs person))} languages")
;; Destructuring
(let (({:keys [name age]} person))
(println f"${name} is ${age}"))
;; Pattern matching with guards
(define (classify n)
(match n
(x when (> x 100) "big")
(x when (> x 0) "small")
(_ "non-positive")))
;; Functional pipelines
(->> (range 1 100)
(filter even?)
(map #(* % %))
(take 5))
;; => (4 16 36 64 100)
;; Nested data access
(define config {:db {:host "localhost" :port 5432}})
(get-in config [:db :host]) ;; => "localhost"
;; Macros
(defmacro unless (test . body)
`(if ,test nil (begin ,@body)))
;; Modules
(module utils (export square)
(define (square x) (* x x)))
;; HTTP, JSON, regex, file I/O, crypto, CSV, datetime...
(define data (json/decode (http/get "https://api.example.com/data")))
📖 完整的语言参考、标准库文档和更多示例,请访问 sema-lang.com/docs
立即试用
sema.run——基于浏览器的在线体验环境,提供 20 多个示例程序。 无需安装。完全在 WebAssembly 中运行。
用一行命令教会你的编码 Agent 使用 Sema
Sema 还很新,你的 Agent 还不了解它。只需一条命令即可解决——将 Agent 速查指南追加到仓库的 AGENTS.md 中(并让 CLAUDE.md 指向它):
curl -fsSL https://sema-lang.com/docs/for-agents.md >> AGENTS.md
ln -s AGENTS.md CLAUDE.md # Claude Code, Cursor, etc. read this
for-agents.md 是一份简明实用指南,面向已经熟悉 Lisp 的大模型。它涵盖了最容易导致生成代码出错的规则,并链接到 /llms.txt,这是一个包含所有文档页面的机器可读索引。Agent 可以只获取所需的页面(例如,/docs/llm/tools-agents.md),而不必加载整份手册。每个文档 URL 也都提供原始 Markdown:在 sema-lang.com/docs/... 链接后追加 .md 即可获取源文件。
安装
安装预构建二进制文件(无需 Rust):
# macOS / Linux
curl -fsSL https://sema-lang.com/install.sh | sh
# Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://github.com/sema-lisp/sema/releases/latest/download/sema-lang-installer.ps1 | iex"
# Homebrew (macOS / Linux)
brew install helgesverre/tap/sema-lang
或者从 crates.io 安装:
cargo install sema-lang
或者从源代码构建:
git clone https://github.com/sema-lisp/sema
cd sema && cargo build --release
# Binary at target/release/sema
对于需要优化二进制文件的本地开发,请使用 jake release-fast 或 cargo build --profile release-fast。二进制文件位于 target/release-fast/sema。此配置文件使用增量编译和并行代码生成,不启用跨 crate LTO。进行性能测量和构建发行版本时,请使用 --release。有关构建耗时和运行时权衡,请参阅构建配置文件测量结果。
sema # REPL (with tab completion)
sema script.sema # Run a file
sema -e '(+ 1 2)' # Evaluate expression
sema --no-llm script.sema # Run without LLM (faster startup)
sema build app.sema -o myapp # Build standalone executable
./myapp # Run without sema installed
Shell 补全
为你的 Shell 生成制表符补全脚本:
# Zsh (macOS / Linux)
mkdir -p ~/.zsh/completions
sema completions zsh > ~/.zsh/completions/_sema
# Bash
mkdir -p ~/.local/share/bash-completion/completions
sema completions bash > ~/.local/share/bash-completion/completions/sema
# Fish
sema completions fish > ~/.config/fish/completions/sema.fish
📖 查看所有 Shell 的完整设置说明:sema-lang.com/docs/shell-completions
📖 查看完整的 CLI 参考、标志和 REPL 命令:sema-lang.com/docs/cli
编辑器支持
每个编辑器插件都位于 sema-lisp 组织下各自的仓库中:
| 编辑器 | 仓库 | 安装 |
|---|---|---|
| VS Code | vscode-sema | ext install sema-lang.sema-lang |
| Zed | zed-sema | Extensions → 搜索 Sema |
| IntelliJ | intellij-sema | JetBrains Marketplace → Sema |
| Neovim | sema.nvim | { "sema-lisp/sema.nvim" } |
| Vim | sema.vim | Plug 'sema-lisp/sema.vim' |
| Emacs | emacs-sema | MELPA → sema-mode |
| Helix | helix-sema | 克隆 + ./install.sh |
| Sublime Text | sublime-sema | Package Control → Sema |
所有插件都提供语法高亮;VS Code、Zed、IntelliJ、Neovim、Emacs、Helix 和 Sublime 还接入了内置的语言服务器(sema lsp),其中一些(VS Code、Zed、IntelliJ、Neovim、Helix)还支持调试(sema dap)——部分插件还会注册 MCP 服务(sema mcp)。Zed、Helix 和 Neovim 使用共享的 tree-sitter-sema 语法进行高亮;其他插件则内置各自的语法。
📖 查看完整安装说明和各编辑器的功能列表:sema-lang.com/docs/editors
Notebook
Sema 内置了一个受 Jupyter 启发的 Notebook 界面,提供浏览器 UI:
sema notebook new my-notebook.sema-nb # Create a notebook
sema notebook serve my-notebook.sema-nb # Open in browser (localhost:8888)
sema notebook run my-notebook.sema-nb # Run all cells headlessly
sema notebook export my-notebook.sema-nb # Export to Markdown
各单元格共享持久环境——前面单元格中的定义可在后续单元格中访问。Notebook 保存为 .sema-nb JSON 文件。
📖 完整的 Notebook 文档:sema-lang.com/docs/notebook
语言工具链
完整工具链开箱即用,无需组装插件:
sema fmt script.sema # Canonical code formatter
sema lsp # Language Server (completions, hover, go-to-def, rename)
sema dap # Debug Adapter (breakpoints, stepping, variable inspection)
sema mcp # Model Context Protocol server for LLM clients
MCP 服务允许 LLM 客户端(Claude Desktop、Cursor、Claude Code)在你的环境中直接编译、格式化、求值和构建 Sema 代码,还可以调用你自己的 deftool Lisp 工具。
示例程序
examples/ 目录中有 50 多个程序:
| 示例 | 功能 |
|---|---|
coding-agent.sema | 完整的编码 Agent,包含文件编辑、搜索和 shell 工具 |
review.sema | 用于审查 git 差异的 AI 代码审查器 |
commit-msg.sema | 根据暂存的更改生成符合约定的提交消息 |
summarize.sema | 总结文件或通过管道传入的输入 |
game-of-life.sema | 康威生命游戏 |
brainfuck.sema | Brainfuck 解释器 |
mandelbrot.sema | ASCII Mandelbrot 集 |
json-api.sema | 获取并处理 JSON API |
test-vision.sema | 视觉提取和多模态聊天测试 |
test-extract.sema | 结构化提取和分类 |
test-batch.sema | 批量/并行 LLM 补全 |
test-pipeline.sema | 缓存、预算、速率限制、重试和回退链 |
test-text-tools.sema | 文本分块、提示词模板、文档抽象 |
test-vector-store.sema | 内存中的向量存储,支持相似度搜索 |
test-kv-store.sema | 基于 JSON 持久化的键值存储 |
expr-evaluator.sema | 使用 match 匹配带标签向量的迷你计算器 |
shape-geometry.sema | 使用 map 模式匹配计算形状的面积/周长 |
http-router.sema | 使用 match 匹配嵌套 map 和守卫条件的 HTTP 路由器 |
destructuring.sema | 全面展示解构(向量、map、lambda) |
demo.sema-nb | 交互式笔记本演示(使用 sema notebook serve 运行) |
为什么选择 Sema?
一句话概括:不需要 LangChain、供应商 SDK、Agent 框架或胶水脚本——Agent 循环、重试、缓存、预算、追踪和工具分发都是语言运行时的一部分,整个程序只有一个二进制文件,可以通过 scp 复制到服务器上。
- 将大模型作为语言原语 — 提示词、消息、对话、工具和 Agent 都是一等数据类型,而不是后来拼接的字符串模板
- 支持多家供应商 — 可在 Anthropic、OpenAI、Gemini、Ollama 和任何兼容 OpenAI 的端点之间切换,也可以在 Sema 中定义自己的供应商
- 可用于流水线 — 响应缓存、回退链、速率限制、带退避的重试、文本分块、提示词模板、向量存储和持久化 KV 存储
- 关注成本 — 内置预算跟踪,附带定价快照(models.dev),并随每个版本更新
- 可观测 — 每次大模型/Agent 运行都会自动通过 OpenTelemetry 追踪(GenAI 语义约定):令牌数、成本、延迟以及完整的
invoke_agent → chat → execute_tool调用树;可导出到 Jaeger、Grafana、Datadog、Langfuse、Arize Phoenix 等——无需手动埋点,默认关闭 - 实用的 Lisp — 闭包、尾调用优化(TCO)、宏、模块、错误处理、HTTP、文件 I/O、正则表达式、JSON,以及全面的标准库
- 独立可执行文件 —
sema build可将程序编译为自包含的二进制文件,并自动追踪导入和打包资源 - 可嵌入 — 提供带构建器 API 的 Rust crate,也可使用
@sema-lang/sema通过 WebAssembly 在 JS 中于客户端运行 Sema - 完整工具链 — 内置格式化程序、语言服务器(LSP)、调试器(DAP)和面向大模型客户端的 MCP 服务
- 包管理器 —
sema pkg可从 git 或实时注册表 pkg.sema-lang.com 拉取依赖,并通过sema.lock固定版本,以实现可复现安装 - 开发者友好 — 支持制表符补全的 REPL、带提示的结构化错误消息,以及 50 多个示例程序
为什么不选择 Sema?
- 不支持延续(
call/cc)或完全卫生的宏(syntax-rules)——提供自动生成符号(foo#)以防止变量捕获 - 单线程——基于
Rc,值无法跨线程共享 - 不支持 JIT——采用字节码编译器和基于栈的虚拟机,不生成原生代码
- 语言较新——表现稳定,但尚未经过大规模实战检验
架构
crates/
sema-core/ NaN-boxed Value type, errors, environment
sema-reader/ Lexer and s-expression parser
sema-vm/ Bytecode compiler and virtual machine
sema-eval/ Trampoline-based evaluator, special forms, modules
sema-stdlib/ Built-in functions across many modules
sema-io/ Process-wide async I/O pool (tokio) behind the core seam
sema-llm/ LLM provider trait + multi-provider clients
sema-workflow/ Dynamic-workflow runtime — journaled runs, bounded fan-out, --resume
sema-otel/ OpenTelemetry tracing (GenAI semantic conventions)
sema-docs/ Canonical builtin docs (powers LSP hover + REPL apropos)
sema-lsp/ Language Server Protocol implementation
sema-dap/ Debug Adapter Protocol server
sema-fmt/ Source code formatter
sema-mcp/ Model Context Protocol server
sema-notebook/ Jupyter-inspired notebook interface with browser UI
sema-wasm/ WebAssembly build for sema.run playground
sema/ CLI binary: REPL + file runner + standalone builder
许可证
MIT — 参见 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。