|
|
hai 3 meses | |
|---|---|---|
| .github | hai 5 meses | |
| agent-lint-action | hai 3 meses | |
| agentexample | hai 3 meses | |
| agentpaas | hai 3 meses | |
| demo | hai 3 meses | |
| deploy | hai 3 meses | |
| docs | hai 3 meses | |
| experiments | hai 3 meses | |
| lambdagent | hai 3 meses | |
| lambdagent_guard | hai 3 meses | |
| link | hai 3 meses | |
| tests | hai 3 meses | |
| webui | hai 3 meses | |
| .dockerignore | hai 5 meses | |
| .env.template | hai 3 meses | |
| .gitignore | hai 3 meses | |
| AGENT_GUIDE.md | hai 3 meses | |
| CONTRIBUTING.md | hai 5 meses | |
| Dockerfile | hai 3 meses | |
| LICENSE | hai 5 meses | |
| QUICK_START.md | hai 3 meses | |
| README.md | hai 3 meses | |
| agent-config.yml | hai 3 meses | |
| docker-compose.dev.yml | hai 3 meses | |
| docker-compose.yml | hai 3 meses | |
| mkdocs.yml | hai 5 meses | |
| setup.sh | hai 5 meses |
A Python DSL that models AI agents as Lambda calculus terms. Every agent is a function, every composition is function composition, every loop is a Y combinator. This is not a metaphor — it is a formal correspondence backed by a Church encoding verification.
Key insight: An (M, D) pair — a language model M plus a dataset/prompt D — is isomorphic to a Lambda term. LLM + Dataset = Lambda term.
Stats: ~11,300 lines of Python | 81 exported symbols | 4 patents filed
ConversationLam maintains full session persistence so the model never loses context mid-conversation, eliminating the hallucination caused by truncated history.provider: claude-code and use your Claude Code subscription directly. No API key, no billing dashboard, no environment variables.from_config() compiles it into a typed Lambda term tree.# agent-config.yml
model:
provider: claude-code
name: sonnet
# Interactive chat
python3 -m agentpaas chat lambda
# Or run the example agent directly
python3 agentexample/agent67/run.py --claude
No API key required -- uses your Claude Code Max Plan subscription.
| Provider | Config value | API Key needed | Notes |
|---|---|---|---|
| Claude Code (Max Plan) | claude-code |
No | Uses local Claude Code subscription |
| Anthropic API | anthropic |
Yes (ANTHROPIC_API_KEY) |
Direct Claude API access |
| OpenAI-compatible | dashscope / openai / deepseek / zhipu / moonshot |
Yes | Any OpenAI-compatible endpoint |
| Ollama (local) | ollama |
No | Runs models locally, requires Ollama installed |
lambdagent maps 11 core agent constructs to Lambda calculus, giving each one a precise denotational semantics:
| # | Lambda Calculus | DSL Construct | Description |
|---|---|---|---|
| 1 | Lambda abstraction λx.body |
Lam(name, prompt) |
An LLM with a system prompt |
| 2 | Application (f x) |
agent(input) |
Run agent on input |
| 3 | Composition λx.g(f(x)) |
f >> g |
Pipeline / chain |
| 4 | Church conditional IF |
If(cond, then_, else_) |
Conditional branching |
| 5 | Y combinator | Loop(body, condition) |
Iterative reasoning (ReAct) |
| 6 | Church pair PAIR |
Pair(f, g) |
Run two agents, return both |
| 7 | Projections FST / SND |
Fst() / Snd() |
Extract from pair |
| 8 | Primitive / Oracle | Tool(name, fn) |
External tool call |
| 9 | Generalized CASE | Route(classifier, routes) |
Multi-way dispatch |
| 10 | Dependent type {x:T\|P(x)} |
Guard(agent, validator) |
Output validation |
| 11 | Environment extension | Memory(agent, store) |
Persistent context |
Plus Par(f, g) as syntactic sugar for parallel execution (via | operator).
| # | Process Calculus | DSL Construct | Description |
|---|---|---|---|
| 12 | Channel c!(v) / c?(x) |
Channel + Send + Receive |
Inter-agent communication |
| 13 | Shared environment | SharedMemory |
Thread-safe shared state |
| 14 | Y_n(Loop + Route) | GroupChat |
Multi-agent group discussion |
| 15 | Dynamic CASE | Handoff |
Runtime dynamic delegation |
| 16 | Concurrent beta-reduction | AsyncPar |
Thread-pool true parallelism |
| Construct | Description |
|---|---|
Skill |
Named, reusable Lambda term with metadata |
SkillPack |
Collection of related skills (like a package) |
SkillRegistry |
Global singleton registry with search/discover |
SkillAgent |
Auto-discovers and executes best skill |
@skill |
Decorator to create and register skills |
| Module | Protocol | Description |
|---|---|---|
MCPServer/Tool |
MCP 2025-11-25 | Connect to MCP servers (HTTP + stdio) |
A2AServer/Client |
Google A2A v0.3 | Publish/discover/call remote agents |
RAGTool |
-- | TF-IDF or ChromaDB retrieval-augmented gen |
AgenticRAG |
-- | Agent decides when to retrieve |
Checkpoint |
-- | Serialize/restore execution state to JSON |
| Construct | Description |
|---|---|
SandboxedTool |
Tool that runs in isolated subprocess with resource limits |
SandboxPolicy |
Security policy (timeout, memory, network, etc.) |
SecureExecutor |
Auto-wraps all Tools in a term tree with sandbox |
ResourceLimiter |
Applies CPU/memory/fd limits via POSIX resource |
@sandboxed |
One-line decorator for sandboxed tool creation |
YAML Config ──→ from_config() ──→ Lambda Term ──→ Runtime ──→ Result
(compiler) (Term tree) (beta-reduction)
┌── Multi-Agent: Channel, GroupChat, Handoff, AsyncPar
├── Skills: Skill, SkillPack, SkillRegistry, SkillAgent
Lambda Term ──→ Runtime ──→ ├── MCP: MCPServer, MCPTool (HTTP + stdio)
├── A2A: AgentCard, A2AServer, A2AClient
├── RAG: RAGTool, AgenticRAG, SimpleVectorStore
├── Checkpoint: save/load execution state
└── Sandbox: SandboxedTool, SecureExecutor, ResourceLimiter
The system has five layers:
lambdagent.core, lambdagent.primitives, lambdagent.extensions) — the 11 core constructs as Python classes, each a subclass of Term.lambdagent.multiagent) — 5 pi-calculus constructs for inter-agent communication, group chat, dynamic delegation, and true parallelism.lambdagent.skills, lambdagent.mcp_client, lambdagent.a2a, lambdagent.rag, lambdagent.checkpoint) — reusable skills, MCP/A2A protocol integration, retrieval-augmented generation, and state persistence.lambdagent.fromconfig) — parses YAML configs into Lambda term trees. Includes schema validation and lint.lambdagent.agentruntime) — executes Lambda terms via beta-reduction, handling LLM calls, MCP tool invocation, memory, and tracing. 支持双执行引擎切换 (recursive/cek/adaptive), 通过 runtime.engine 配置。CEK 引擎提供逐步成本监控、暂停/恢复和循环检测能力。pip install lambdagent
For LLM provider support:
pip install lambdagent[anthropic] # Anthropic Claude
pip install lambdagent[openai] # OpenAI-compatible (Dashscope, etc.)
from lambdagent import Lam, Compose, Loop, Tool, Memory
# A single agent is a Lambda abstraction
writer = Lam("writer", "You are a technical writer. Write clear documentation.")
# Composition is function composition
reviewer = Lam("reviewer", "Review the text for clarity and correctness.")
pipeline = writer >> reviewer # = lambda x. reviewer(writer(x))
# ReAct agent is a Y combinator
searcher = Tool("search", lambda q: web_search(q))
researcher = Loop(
body=Lam("think", "Analyze the question. Use search if needed."),
condition=lambda result: "DONE" in result,
max_iterations=10,
)
# Add memory for persistent context
agent = Memory(researcher, strategy="local", size=20)
# Execute = beta-reduction
result = agent("What are the latest advances in LLM agents?")
agentId: research-assistant
name: ResearchAssistant
type: react
systemPrompt: |
You are a research assistant. Search for information,
analyze it, and produce a comprehensive report.
model:
provider: dashscope
name: qwen3-max-2026-01-23
temperature: 0.7
maxTokens: 4096
react:
maxSteps: 15
runtime:
engine: recursive # recursive | cek | adaptive
memory:
enabled: true
strategy: local
size: 20
mcp:
onlineTool:
example-mcp-server:
- everything_get_sum
localTools:
- terminate
from lambdagent import from_config
agent = from_config("agent-config.yml")
result = agent("Summarize recent progress in AI safety research")
from lambdagent import Lam, GroupChat, SharedMemory
researcher = Lam("researcher", "You are a researcher. Find evidence.")
critic = Lam("critic", "You are a critic. Challenge weak arguments.")
synthesizer = Lam("synthesizer", "You synthesize the discussion into conclusions.")
chat = GroupChat(
agents=[researcher, critic, synthesizer],
max_rounds=6,
scheduler="round_robin",
)
result = chat("Should we invest in quantum computing?")
from lambdagent import mcp_tools, mcp_tool
# Get all tools from an MCP server
tools = mcp_tools("http://localhost:3000/mcp")
# Or get a single tool
search = mcp_tool("http://localhost:3000/mcp", "search")
result = search({"query": "AI agents"})
from lambdagent import create_rag, AgenticRAG, Lam
rag = create_rag(["Python is a programming language.", "Lambda calculus is..."])
agent = Lam("qa", "Answer questions using the provided context.")
agentic = AgenticRAG(agent, rag, decider=lambda x: "?" in x)
result = agentic("What is Lambda calculus?")
from lambdagent import Context, save_context, load_context
ctx = Context()
agent("long running task", ctx)
save_context(ctx, "checkpoint.json", last_input="long running task")
# Later, resume:
ctx = load_context("checkpoint.json")
agent("continue from here", ctx)
from lambdagent import SandboxedTool, SandboxPolicy, SecureExecutor, sandboxed
# One-line decorator
@sandboxed(timeout=10, memory_mb=128)
def risky_calc(x):
return eval(x)
# Or explicit construction with policy presets
tool = SandboxedTool("calc", lambda x: eval(x), policy=SandboxPolicy.strict())
# Secure an entire term tree — wraps all Tools in sandboxes
secure_tree = SecureExecutor(policy=SandboxPolicy.default()).sandbox_all_tools(agent)
python nl2agent.py "Build a research assistant that can search the web and write reports, up to 20 steps, with memory"
Or programmatically:
from nl2agent import one_sentence_to_agent
one_sentence_to_agent(
"Build a code review pipeline: check security, then style, then performance",
task="Review this Python function: def login(u, p): ..."
)
# Compile YAML to Lambda term (no execution)
lambdagent compile agent-config.yml
# Compile and execute
lambdagent run agent-config.yml "Write a quicksort in Python"
# Interactive REPL
lambdagent repl agent-config.yml
# Static analysis (lint)
lambdagent lint agent-config.yml
# Export pure Lambda expression
lambdagent lambda agent-config.yml
# Unix pipes work (composition = pipe)
echo "Hello world" | lambdagent run agent-config.yml -
Term — Abstract base class. All constructs are Terms.Context — Evaluation environment with beta-reduction tracing.Lam(name, prompt) — Lambda abstraction. Wraps an LLM call.Compose(f, g) / f >> g — Function composition.If(cond, then_, else_) — Church conditional.Loop(body, condition) — Y combinator with termination.Pair(f, g) / Par(f, g) — Church pair / parallel execution.Fst() / Snd() — Pair projections.Tool(name, fn) — External oracle (MCP tool, shell command, etc.).Route(classifier, routes) — Generalized Church boolean (CASE).Guard(agent, validator) — Dependent type / output validation.Memory(agent, store) — Environment extension with persistent state.Channel(name, capacity) — pi-calculus channel for inter-agent communication.Send(agent, channel) — Send agent output to channel.Receive(channel, handler) — Receive from channel, optionally process with handler.SharedMemory(store, append_only) — Thread-safe shared state across agents.GroupChat(agents, scheduler, max_rounds) — Multi-agent group discussion (Y + Route).Handoff(selector, registry, fallback) — Runtime dynamic delegation.AsyncPar(*agents) — True parallel execution via thread pool.Skill(name, term, description, signature, tags) — Named, reusable Lambda term with metadata.SkillPack(name) — Collection of related skills.SkillRegistry() — Global singleton registry (search, discover, build_route).SkillAgent(classifier, registry) — Auto-discovers and executes best skill.@skill(name, description, tags) — Decorator to create and auto-register skills.MCPServer.http(url) / MCPServer.stdio(command) — Connect to MCP servers.MCPTool(server, tool_name) — MCP tool wrapped as lambdagent Term.mcp_tools(url) — One-liner to get all tools from a server.mcp_tool(url, name) — One-liner to get a single tool.AgentCard — A2A Agent capability description (JSON).A2AServer(agent, port) — Publish agent as A2A HTTP service.A2AClient(url) — Call remote A2A agent as local Term.skill_to_agent_card(skill) — Convert Skill to AgentCard.RAGTool(store, top_k) — Retrieval tool (TF-IDF or ChromaDB).AgenticRAG(agent, rag, decider) — Agent decides when to retrieve.SimpleVectorStore() — Zero-dependency TF-IDF vector store.create_rag(documents, top_k) — One-liner to create RAG tool.Checkpoint(context, shared_data) — Execution state snapshot.CheckpointManager(directory) — Manage multiple checkpoints with auto-cleanup.save_context(ctx, path) / load_context(path) — Save/restore Context.SandboxedTool(name, fn, policy) — Tool running in isolated subprocess with resource limits.SandboxPolicy(timeout, memory_mb, network, ...) — Security policy. Presets: .strict(), .default(), .permissive().SecureExecutor(policy) — Auto-wraps all Tools in a term tree via sandbox_all_tools().ResourceLimiter — Applies POSIX RLIMIT_CPU, RLIMIT_AS, RLIMIT_NOFILE, RLIMIT_NPROC.@sandboxed(timeout, memory_mb, ...) — Decorator for one-line sandboxed tool creation.SandboxViolation, TimeoutViolation, MemoryViolation, OutputViolation.from_config(path_or_dict) — YAML to Lambda term.lint_config(path_or_dict) — Static analysis.to_lambda_expr(path_or_dict) — Export formal Lambda expression.describe_config(path_or_dict) — Human-readable structure description.Runtime — Executes Lambda terms with LLM backends.ReActEngine — Implements the Y combinator loop for ReAct agents.MCPClient — Model Context Protocol tool invocation.TraceStore — Records beta-reduction traces for debugging.lambdagent is grounded in a formal correspondence between agent constructs and Lambda calculus:
If construct uses Church booleans, Pair/Fst/Snd use Church pairs, and Route uses generalized Church numerals.Lam and application together can encode S and K combinators, from which all computable functions follow.Loop is not ad-hoc iteration; it is the Y combinator Y = λf.(λx.f(x x))(λx.f(x x)) with a bounded unfolding (max_iterations) to ensure termination.For the full formal treatment, see the accompanying paper (paper.tex).
MIT License — Copyright (c) 2025 kenny67nju
If you use lambdagent in academic work, please cite:
@software{lambdagent2025,
title = {lambdagent: A Lambda Calculus Agent DSL},
author = {kenny67nju},
year = {2025},
url = {https://github.com/kenny67nju/lambdagent},
}