Python bindings for λ-Tool: safe LLM tool composition with type checking.
λ-Tool is a typed intermediate representation that LLMs generate instead of Python for tool composition. The type checker verifies code is safe before execution -- no missing fields, no unhandled errors, no infinite loops.
- Python 3.10+
- The
lambda_toolCLI binary (build from source)
# Build the OCaml CLI
cd lambda-tool
opam install . --deps-only && eval $(opam env)
dune build && dune installpip install lambda-tool-pythonThe package auto-discovers the lambda_tool binary from PATH, dune build output, or opam install locations.
from lambda_tool import LambdaTool, LambdaToolError
lt = LambdaTool()
# Type check a program
result = lt.typecheck("let x = 1 + 2 in x")
print(result.type) # "Int"
print(result.effects) # []
# Execute with real tool implementations
result = lt.run("""
tool query: String -{Read}-> {rows: List {id: Int, name: String}};
let get_name = fn row: {id: Int, name: String} => row.name in
match exec tool query "SELECT * FROM users" {
Ok(result) => map get_name result.rows,
Err(e) => []: String
}
""", executors={
"query": lambda arg: {"rows": [{"id": 1, "name": "Alice"}]},
})
print(result.value) # ["Alice"]
print(result.type) # "List String"
print(result.effects) # ["Read"]Type errors are caught before execution:
try:
lt.typecheck("let x = 1 + true in x")
except LambdaToolError as e:
print(e.errors) # ["Type mismatch at line 1, col 9: expected Bool, got Int"]Runtime tool errors are caught and converted to Err values:
def flaky_tool(arg):
raise ConnectionError("network down")
result = lt.run("""
tool fetch: String -{Network}-> String;
match exec tool fetch "url" {
Ok(data) => data,
Err(e) => "fallback"
}
""", executors={"fetch": flaky_tool})
print(result.value) # "fallback"Create a wrapper instance. Pass binary to override auto-discovery of the lambda_tool CLI.
Type check without executing. Returns TypeCheckResult with:
.type(str) -- the inferred type.effects(list[str]) -- the required effects ("Read","Write","Network")
Raises LambdaToolError on parse or type errors.
Type check and execute. Returns RunResult with:
.value-- the program's return value (decoded to Python).type(str) -- the inferred type.effects(list[str]) -- the required effects
Raises LambdaToolError on parse, type, or runtime errors.
Each executor is a Python callable (arg) -> result:
| Description | |
|---|---|
| Input | Decoded tool argument: dict for records, str/int/bool for primitives, list for lists |
| Output | Any JSON-serializable value (dict, list, str, int, bool, None) |
| Errors | Raise any exception to signal a tool error (caught and converted to Err) |
| λ-Tool | Python |
|---|---|
42, true, "hello" |
42, True, "hello" |
{name = "Alice"} |
{"name": "Alice"} |
[1, 2, 3] |
[1, 2, 3] |
Ok(v) |
("Ok", v) |
Err(e) |
("Err", e) |
() |
None |
pytest tests/ -v17 tests covering type checking, execution, interactive tool callbacks, traverse, conditionals, and edge cases.
- lambda-tool: The core OCaml implementation (type checker, interpreter, CLI)
- minilambda: Minimal agent demo using Claude + λ-Tool
LGPL-3.0-or-later. Check LICENSE for details. © Sarthak Shah (matchcase), 2026.