Weft is a scripting language that ships everything you need to build agent tools, HTTP services, and devops scripts. No interpreters to install. No dependencies to manage.
# one-line install (no Go required)$ curl -fsSL https://weftproject.dev/install.sh | sh
$ weft doctor
$ cat agent.weft
fnlookup(name) {
db := db.open("sqlite:app.db")?
db.query("SELECT * FROM users WHERE name = ?", [name])?
}
fnmain-> Result {
// the model calls your functions
reply := llm.ask("Find user Alice", [
llm.tool("lookup", lookup),
])?
say(reply)
}
65+stdlib packages
0runtime dependencies
1binary to deploy
4LLM providers built in
Why another language?
We kept writing the same glue in Python and Bash: call an LLM, hit an API, check a server, parse some config. Each time we needed a virtualenv, a Dockerfile, or three layers of error handling. Weft is the language we wanted for those scripts.
Errors are values
Result and ? instead of try/catch. You see every failure path in the code. No surprises at 3am.
Concurrency is default
map and filter fan out automatically. spawn, channels, race, timeout. No async/await coloring.
Ship the binary
go build once. Copy to your server. No Go on the target, no interpreter, no package manager at deploy time.
LLM tool calling in 10 lines
Give a model your functions. It decides when to call them, you handle the results. Works with OpenAI, Anthropic, Ollama, and vLLM — swap providers with an env var.
Multi-step agents loop automatically: the model calls tools, reads results, and calls more tools until it has an answer. Set max_steps to cap iterations.
llm.askllm.toolllm.agentllm.chat
fnget_weather(city) {
http.get_json("https://wttr.in/$city?format=j1")?
}
fnsearch_docs(query) {
db := db.open("sqlite:docs.db")?
db.query("SELECT * FROM docs WHERE body LIKE ?",
["%$query%"])?
}
fnmain-> Result {
reply := llm.ask("What's the weather where our SF office is?", [
llm.tool("get_weather", get_weather),
llm.tool("search_docs", search_docs),
], {"max_steps": 5})?
say(reply)
}
// multi-turn conversationfnmain-> Result {
msgs := [
{"role": "system", "content": "You are a code reviewer."},
{"role": "user", "content": "Review this: fn add(a,b) { a + b }"},
]
review := llm.chat(msgs)?
say(review)
// streaming for long responses
text := llm.stream_text("Write a haiku about error handling")?
say(text)
// structured extraction
data := llm.extract("Paris is the capital of France", {
"city": "string",
"country": "string",
})?
say(data.city) // "Paris"
}
Chat, stream, extract
Simple chat for quick prompts. Multi-turn with message arrays. Stream long responses token by token. Extract structured data from free text.
Run locally with Ollama or vLLM — same code, same API, no vendor lock-in. Just set WEFT_PROVIDER=ollama.
LLMs return free text. mold pours it into the shape you need — define a schema, validate the output, generate JSON Schema or tool params for the model to follow.
Pairs with ml for embeddings and RAG, and tokensave for context management. The full agent stack, installable as packages.
moldmltokensavewarp
use mold
fnmain-> Result {
schema := mold.model({
"name": mold.string({"min": 1}),
"email": mold.string({"format": "email"}),
"age": mold.integer({"min": 0, "max": 150}),
"role": mold.one_of(["admin", "user", "guest"]),
})
// ask the model to fill the schema
spec := mold.tool_params(schema)
reply := llm.ask("Create a user for Alice, age 30", [
llm.tool("create_user", create_user, spec),
])?
say(reply)
}
Train your own Weft writer
Teach a model to emit Weft instead of Python. Private by default — training data never leaves your machines unless you explicitly upload it.
Prepare data
Build a supervised fine-tune dataset from the gold corpus, your own domain examples, or tokensave's clarified memory. All local.
Train locally
LoRA fine-tune on open models (Qwen, Llama, Gemma) on your GPU. Presets handle the config. Air-gapped mode for secure environments.
Serve and test
Host your adapter with vLLM or TGI. Point WEFT_API_BASE at it. Evaluate accuracy against gold prompts.
weft train handles the full pipeline: prepare data, run LoRA on open frontier models, evaluate accuracy, then serve via any OpenAI-compatible host.
Your private domain data stays on your machine. Use --from to merge confidential examples. WEFT_TRAIN_PRIVATE=1 blocks any accidental cloud upload.
weft gen turns English into Weft scripts — with your fine-tuned model or any provider.
weft train prepareweft train finetuneweft train evalweft gen
Any provider, same code
Switch between OpenAI, Anthropic, Ollama, and vLLM with one env var. The same llm.chat, llm.ask, and llm.stream calls work everywhere — including your fine-tuned model.
Run fully offline with Ollama on your laptop, or hit a private vLLM cluster in your VPC. No SDK lock-in, no vendor-specific code paths.
OpenAIAnthropicOllamavLLM
# OpenAI (default)$ export OPENAI_API_KEY=sk-...
$ weft run agent.weft
# Anthropic$ export WEFT_PROVIDER=anthropic
$ export ANTHROPIC_API_KEY=sk-ant-...
$ weft run agent.weft # same code, different model# Local Ollama (offline)$ export WEFT_PROVIDER=ollama
$ export OLLAMA_MODEL=llama3.2
$ weft run agent.weft # same code, no internet# Your fine-tuned model on vLLM$ export WEFT_PROVIDER=vllm
$ export VLLM_BASE_URL=http://gpu-box:8000/v1
$ export WEFT_MODEL=weft-writer
$ weft run agent.weft # your model, your infra
# air-gapped training (no internet on GPU box)$ weft train offline -o weft-airgap --expand \
--from /secure/domain.jsonl
# copy weft-airgap/ via USB to GPU machine# on the air-gapped box:$ export HF_HUB_OFFLINE=1
$ export TRANSFORMERS_OFFLINE=1
$ weft train finetune --private --skip-prepare \
--data weft-airgap \
--model /models/Qwen2.5-7B-Instruct \
--out weft-lora
Air-gapped environments
For classified or regulated data: bundle the dataset and config on an internet-connected machine, copy to the GPU box via USB or internal storage, train with no network access.
Set WEFT_TRAIN_PRIVATE=1 to block any accidental cloud upload across the whole pipeline. The model weights, training data, and LoRA adapters never touch a public network.
weft train offlineair-gappedWEFT_TRAIN_PRIVATE
fnmain-> Result {
mem := sysinfo.memory()?
disk := sysinfo.disk("/")?
up := sysinfo.uptime()?
say("up ${up.human}, ram ${mem.percent}%")
for port in [80, 443, 5432] {
p := netutil.tcp_ping("localhost", port)?if p.open {
say(" :$port ${p.latency_ms}ms")
} else {
log.error(" :$port down")
}
}
nginx := proc.find("nginx")?
say("nginx: ${len(nginx)} processes")
}
DevOps without the glue
System metrics, process management, port scanning, DNS lookups — all in the stdlib. No shelling out to free -m and parsing the output.
Write your runbooks in a language that handles errors properly and runs the same on every machine.
sysinfoprocnetutilshfssecretssignallog
Packages with guardrails
Third-party packages install to vendor/ with a lockfile. Every publish is ed25519-signed.
The capability system restricts what packages can touch — a JSON validation library can't read your filesystem or call home unless you explicitly grant it.
// $ weft registry install mold// $ weft registry install ml// capabilities enforced per-package:// mold → pure (no fs, no http)// ml → fs onlyuse mold
use ml
fnmain-> Result {
// mold can't touch the network// ml can read files but can't call home
schema := mold.model({"q": mold.string()})
vec := ml.embed("search query")?
say(len(vec))
}