LLM function calling on steroids using Abstract Syntax Trees.
Project description
🌲 treelang
Turn your toolboxes into executable Abstract Syntax Trees (ASTs) that Large Language Models can plan in a single shot. treelang lets you express arbitrarily complex workflows, keep sensitive values out of the LLM, and reuse the resulting programs as shareable, cacheable trees.
Highlights
- One LLM call, full plan – generate an AST for a complete solution without the expensive function-call loop.
- Complex workflows – conditionals, higher-order functions (
map,filter,reduce), and nested tool invocations all live in one tree. - Secure + green – the LLM never sees tool results; you evaluate nodes locally while controlling cost and compliance.
- Model Context Protocol native – ships with an MCP client provider but can work with any tool registry through the
ToolProviderabstraction. - Composable outputs – turn ASTs into callable tools (
AST.tool) or serialize/describe them for sharing, caching, or review.
What you can build
- Enterprise copilots that must orchestrate dozens of tools with branching logic.
- Automations that need to fan out over datasets (e.g., score/map/filter large collections asynchronously).
- Reusable skills: persist an AST, describe it with
EvalResponse.describe(), and redeploy it as a tool on your MCP server. - LLM evaluation loops: ask for the tree (
EvalType.TREE) to inspect reasoning before execution, or walk it immediately for answers.
Quick start
Requirements
- Python 3.12+
- An OpenAI API key (
OPENAI_API_KEY) and optionalOPENAI_MODELoverride (defaults togpt-4o-2024-11-20) - A source of tools: an MCP server, or your own provider implementing
treelang.ai.provider.ToolProvider
Install
pip install treelang
Wire up tools (MCP)
import asyncio
from contextlib import AsyncExitStack
from mcp import ClientSession
from mcp.client.streamable_http import streamable_http_client
from treelang.ai.arborist import EvalType, OpenAIArborist
from treelang.ai.provider import MCPToolProvider
async def build_arborist(stack: AsyncExitStack) -> OpenAIArborist:
try:
await stack.__aenter__()
# Connect to a streamable HTTP server
read_stream, write_stream, _ = await stack.enter_async_context(
streamable_http_client("http://localhost:8000/mcp")
)
# Create a session using the client streams
session = await stack.enter_async_context(
ClientSession(read_stream, write_stream)
)
# Initialize the connection
await session.initialize()
# Create the Arborist
provider = MCPToolProvider(session)
arborist = OpenAIArborist(provider=provider, model="gpt-4o")
return arborist
except Exception:
print ("Error building the Arborist")
await stack.aclose()
raise
Ask a question (MCP)
async def run():
stack = AsyncExitStack()
arborist = await build_arborist(stack)
response = await arborist.eval(
query="Compare next weekend flights BOS➜SFO and summarize the cheapest option.",
type=EvalType.WALK, # change to EvalType.TREE to inspect the JSON AST instead
)
print(response.content) # fully-evaluated tool output
if (stack):
await stack.aclose()
if __name__ == "__main__":
asyncio.run(run())
Use response.jsontree with AST.parse() or AST.repr() if you want to log, cache, or transform the raw tree.
Tree-first workflow
- Generate –
OpenAIArboristassembles an AST using your available tools. - Inspect – represent the tree as JSON, describe it with
EvalResponse.describe(), or pretty-print it usingAST.repr(). - Evaluate –
AST.eval(tree, provider)asynchronously executes every node; the LLM never sees intermediate values. - Package –
await AST.tool(tree, provider)turns a tree into a callable tool so you can add it back to your MCP server.
Architecture at a glance
- Arborist (
treelang/ai/arborist.py) – orchestrates LLM calls, maintains history via the optionalMemoryinterface, and decides whether to return ASTs or walked results. - Tool providers (
treelang/ai/provider.py) – abstract how tools are discovered/invoked. We ship an MCP client implementation and a template for custom providers. - Selectors (
treelang/ai/selector.py) – plug in your own tool filtering logic;AllToolsSelectorships by default. - Trees (
treelang/trees/tree.py) – immutable node classes plus helpers such as async traversal, repr generation, and turning trees into callable tools.
Resources & examples
- Cookbook notebooks (
cookbook/) walk through building trees, call patterns, and evaluation strategies. - Reproducible benchmark (
evaluation/eval.py) runs versioned deterministic cases without credentials, records machine-readable quality and resource metrics, and checks them against committed regression baselines. A separate manual/scheduled live workflow records comparable model quality, latency, token, and cost evidence without exposing credentials to pull requests. Seeevaluation/README.mdfor commands and baseline policy. - Unit tests (
tests/) cover the AST core and are a good reference for expected behavior when extending nodes.
Contributing & local development
We actively welcome contributions—see CONTRIBUTING.md for the full workflow.
Maintainers publish signed, provenance-attested releases through PyPI Trusted Publishing. See RELEASING.md for versioning, promotion, publishing, and verification instructions.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file treelang-0.10.0.tar.gz.
File metadata
- Download URL: treelang-0.10.0.tar.gz
- Upload date:
- Size: 151.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4ab0a901560feab0f43780f5831c180bbac6b43408ac9449331c003be97e8516
|
|
| MD5 |
b93811af9eb6dacac80c2e83dcb756a0
|
|
| BLAKE2b-256 |
f821c7d86e20718ddc0af5a71b153f85f5f6fe1600263716d3a52acfbbad9b9c
|
Provenance
The following attestation bundles were made for treelang-0.10.0.tar.gz:
Publisher:
release.yml on cs0lar/treelang
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
treelang-0.10.0.tar.gz -
Subject digest:
4ab0a901560feab0f43780f5831c180bbac6b43408ac9449331c003be97e8516 - Sigstore transparency entry: 2203121549
- Sigstore integration time:
-
Permalink:
cs0lar/treelang@b94b1f9fde53c6323fc7997ba11d714741e5a61a -
Branch / Tag:
refs/tags/v0.10.0 - Owner: https://github.com/cs0lar
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b94b1f9fde53c6323fc7997ba11d714741e5a61a -
Trigger Event:
push
-
Statement type:
File details
Details for the file treelang-0.10.0-py3-none-any.whl.
File metadata
- Download URL: treelang-0.10.0-py3-none-any.whl
- Upload date:
- Size: 27.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f6e6cf34dd81bc1985e040433170ba895d4e880f99637a10093bef5459480bda
|
|
| MD5 |
90851b0a60ef83d62a61f4813402b1bb
|
|
| BLAKE2b-256 |
6a29916764eba075f64c7eb187adf12764cf8055bbb5c380365703dd691377e3
|
Provenance
The following attestation bundles were made for treelang-0.10.0-py3-none-any.whl:
Publisher:
release.yml on cs0lar/treelang
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
treelang-0.10.0-py3-none-any.whl -
Subject digest:
f6e6cf34dd81bc1985e040433170ba895d4e880f99637a10093bef5459480bda - Sigstore transparency entry: 2203121618
- Sigstore integration time:
-
Permalink:
cs0lar/treelang@b94b1f9fde53c6323fc7997ba11d714741e5a61a -
Branch / Tag:
refs/tags/v0.10.0 - Owner: https://github.com/cs0lar
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b94b1f9fde53c6323fc7997ba11d714741e5a61a -
Trigger Event:
push
-
Statement type: