▶ Every era of software was unlocked by a language made for it

Weft is the foundation for AI systems

Made for what will kill AI agents

The first programming language designed for AI to write. Tangle, the coding assistant built into Weft, writes it for you, and you read it as a graph.

Free and open source. Runs on your machine. Come say hi on Discord

Early, but it runs most projects. Cloud deploy works on GCP today.

Not ready? Follow the build

No spam. Occasional updates on what I ship and what is coming.

Our founder red-teamed AI since davinci for

OpenAI
Anthropic
METR
Amazon AGI

▶ Meet Tangle

You never have to learn this language: describe it, Tangle builds it

Tangle in Claude Code: the request for a WhatsApp voice-note bot on the left, the program it built on the right, running

Left: a real request for a WhatsApp bot that transcribes voice notes. Right: the program Tangle built, running.

From an idea to a deployed product, without you steering each step.

30min

for Tangle to build what the best AI models take tens of hours to write alone.

  1. 01

    Tells you the plan first

    And asks you when there is a real choice to make.

  2. 02

    Writes expert prompts and missing pieces

    Expert-written prompts, and a new building block when none does the job.

  3. 03

    Tests every piece

    Every piece has run, and anything wrong has been fixed, before you see it.

  4. 04

    Fixes a case and keeps it fixed

    Give it a failing case. It fixes it, then freezes the right answer.

  5. 05

    Builds the frontend

    A site or an app that talks to your program.

  6. 06

    Deploys it

    On your own cloud, so it runs with your laptop closed.

Works with

Claude Code Cline Codex Cursor Devin Desktop Gemini CLI GitHub Copilot Junie Kilo Code OpenCode

▶ Try it

This is Weft: Tangle writes it, you read the graph

A Weft program shown as code and as a graph, side by side in VS Code

Install Weft to click around in yours.

▶ Scoped runs

Run any piece of the program on its own: start anywhere, stop anywhere

01

Start from any input

Made-up values, a saved real input, or live services. Everything else is reused from the last run.

02

Freeze the cases that matter

Fix a case that failed in production, then freeze the right answer. After any change, see exactly what moved.

03

The loop Tangle runs

Run a piece, read the result, fix, run again. That is how Tangle tests on its own.

weft · zsh
$weft run --from classify='{"text":"the invoice is wrong"}' --save invoice --target reply
✓classify → billing
✓reply → "Sorry for the trouble…"
Tangle reads reply: it apologises and never mentions the invoice. It rewrites the prompt.
$weft run --seed --target reply
↻classify reused from the last run
✓reply names the invoice, offers a fix
$weft freeze invoice --expect reply
✓froze examples/invoice.json from run 7c41e2 (6 wires, 0 answers)

▶ Why orchestration

Orchestration beats agents, every time: small steps win four ways

01 · Who decides what happens

Reliable

The program holds the job together, so no single model has to keep track of everything.

An agent decides as it goesYou set the structure up frontstart???classifychecksend

02 · How good the work is

Smarter

Each model only sees its own step, so it does that step better.

One agent juggling everything

the goalevery toolall the historyevery edge case

Each step handed just its part

classify the message
look up the order number
reply the order and the question

03 · How long it takes

Faster

Steps run side by side, where an agent goes one at a time.

0s30s60s90s
An agent · one at a time90s
search the web
read the CRM
scan the inbox
check the calendar
A graph · all at once24s
search the web
read the CRM
scan the inbox
check the calendar

04 · What it costs

Cheaper

At every move an agent re-reads the whole conversation, and you pay for it. Each step here pays once.

An agent47k tokens

each call re-reads the whole conversation

A graph9k tokens

each step reads only its own input

▶ Flexibility

Every step can be as strict as code, or as free as a full agent, or anything in between

A bare agent is just one step with the dial turned all the way up.

Orchestration · the same run, freedom set per step

classify

Locked

does one exact thing

research

Full agent

anything can happen

draft

Scoped agent

free, but only these tools

send

Locked

does one exact thing

turn the dial from pure logic, up to a full agent, anywhere in between

An agent · one step, freedom maxed everywhere

anything can happen, the whole way · you can’t see in

full freedom is the only setting, and it covers everything at once

▶ Comparison

So why isn’t everyone building orchestrations yet?

Tangle + Weft

Built for orchestration

Flexible
Scales to production
Helps you build orchestrations
No expertise required

Traditional languages

You fight the language

Flexible
Scales to production
Helps you build orchestrations
No expertise required

Visual flow builders

Locked to pre-made blocks

Flexible
Scales to production
Helps you build orchestrations
No expertise required

An agent’s one edge is that it starts fast. Tangle builds so fast that building, then running, still beats it.

Traditional code
build
AI agent
run
Tangle + Weft
build
run

build + run, end to end, beats the agent in most real cases

▶ Custom tools

Give your AI tools no one else can: built for your exact task, in minutes

To the llm, buy is one tool. Inside, it’s the tiers, approvals and secure payment you built.

shop until the order is done
LLM

pick the next action to take

Web Search

search the web for offers

Send Email

ask the supplier a question

Group

buy within the spending rules

buy within the spending rules
Switch

route the order by its amount

under €100

buy now, capped €1k/hr

€100–1k

a teammate approves

over €1k

another team signs off

HTTP Request

pay through the secure gateway

▶ Who it's for

Who this is for

Hobbyists & small businesses

Build the things that make your life easier

A phone line that books your clients, a bot that runs your store. Describe it and ship it the same day.

Vertical-AI & enterprises

Robust systems running at scale

You bring the domain expertise, we embed with your team. White-label it, run it on your own servers, audit every step.

▶ Humans

When the AI needs a human, it asks, then waits for days with nothing running

outreach · run

paused
LLM

draft the email to this lead

Human

approve or skip this lead

Send Email

send the email once it's approved

Weft tasks
Outreach review Approve or skip this lead
1 / 5

Lead

Dana Ruiz · Head of Platform Kettlewick Freight

Subject

Message

▶ Python vs Weft

The same system, in Python vs Weft: An inbox assistant

Pythoninbox_bot.py
not finished
import os, json, time, base64, threading, logging
from email.mime.text import MIMEText
from google.oauth2.credentials import Credentials
from google.auth.transport.requests import Request
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
import anthropic, psycopg2, psycopg2.extras
from flask import Flask, request, render_template_string, abort

SCOPES = ["https://www.googleapis.com/auth/gmail.readonly", "https://www.googleapis.com/auth/gmail.send"]
log = logging.getLogger("inbox-bot")
app = Flask(__name__)

def gmail_service():
    creds = Credentials.from_authorized_user_file("token.json", SCOPES) if os.path.exists("token.json") else None
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token: creds.refresh(Request())
        else: raise RuntimeError("run the oauth flow first")  # TODO: who does this on the server?
        open("token.json", "w").write(creds.to_json())
    return build("gmail", "v1", credentials=creds, cache_discovery=False)

gmail, llm = gmail_service(), anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
db = psycopg2.connect(os.environ["DATABASE_URL"], cursor_factory=psycopg2.extras.RealDictCursor)

def decode_body(payload):
    if payload.get("body", {}).get("data"): return base64.urlsafe_b64decode(payload["body"]["data"]).decode("utf-8", "replace")
    for part in payload.get("parts", []) or []:
        if part.get("mimeType") == "text/plain" and part["body"].get("data"): return decode_body(part)
    for part in payload.get("parts", []) or []:
        found = decode_body(part)
        if found: return found  # html only? strip tags? attachments?
    return ""

def draft_reply(text, attempt=0):
    try:
        r = llm.messages.create(model="claude-sonnet-5-5", max_tokens=1024, messages=[{"role": "user", "content": text}])
        return "".join(b.text for b in r.content if b.type == "text")
    except (anthropic.RateLimitError, anthropic.APIConnectionError) as e:
        if attempt >= 5: raise
        time.sleep(2 ** attempt); return draft_reply(text, attempt + 1)

def poll_forever():
    seen = {r["msg_id"] for r in query("SELECT msg_id FROM reviews")}
    while True:
        try:
            res = gmail.users().messages().list(userId="me", q="label:inbox -from:me", maxResults=50).execute()
        except HttpError as e:
            log.warning("gmail list failed: %s", e); time.sleep(30); continue
        for m in res.get("messages", []):
            if m["id"] in seen: continue
            msg = gmail.users().messages().get(userId="me", id=m["id"], format="full").execute()
            headers = {h["name"].lower(): h["value"] for h in msg["payload"]["headers"]}
            draft = draft_reply(decode_body(msg["payload"]))
            execute("INSERT INTO reviews (msg_id, thread_id, sender, message_id, draft, status) VALUES (%s,%s,%s,%s,%s,'pending')",
                    (m["id"], msg["threadId"], headers.get("from"), headers.get("message-id"), draft))
            seen.add(m["id"]); notify_reviewer(m["id"])  # slack? email? sms?
        time.sleep(60)

@app.route("/review/<msg_id>", methods=["GET", "POST"])
def review(msg_id):
    row = one("SELECT * FROM reviews WHERE msg_id = %s", (msg_id,)) or abort(404)
    if request.method == "GET": return render_template_string(REVIEW_PAGE, row=row)  # auth? csrf?
    if request.form.get("decision") != "send": return mark(msg_id, "rejected")
    reply = MIMEText(request.form["reply"])
    reply["To"], reply["In-Reply-To"], reply["References"] = row["sender"], row["message_id"], row["message_id"]
    raw = base64.urlsafe_b64encode(reply.as_bytes()).decode()
    gmail.users().messages().send(userId="me", body={"raw": raw, "threadId": row["thread_id"]}).execute()
    ...

# query, execute, one, mark, notify_reviewer, REVIEW_PAGE, the
# schema, the deploy, restarts mid-review, a second worker, ...
...
Weftmain.weft
30 lines, the whole program
1 google = GoogleAccess
2
3 email = GmailNewEmail {
4 account: google.access
5 query: "label:inbox -from:me"
6 }
7
8 draft = LlmInference -> (response: String) {
9 prompt: email.body
10 provider: OpenRouterProvider { model: "anthropic/claude-sonnet-5.5" }.provider
11 params: LlmParams {
12 systemPrompt: "Draft a short, friendly reply to this email."
13 }.params
14 }
15
16 review = HumanQuery {
17 fields: [
18 { "kind": "editable_textarea", "key": "reply" },
19 { "kind": "approve_reject", "key": "send" }
20 ]
21 reply: draft.response
22 }
23
24 send = GmailSend {
25 _should_flow: review.send_approved
26 account: google.access
27 to: email.from
28 replyTo: email.id
29 text: review.reply
30 }

Fewer lines, so the AI builds faster and gets more right.

The compiler catches a broken system before it runs.

▶ Dynamic vocabulary

The vocabulary is yours to define Build the node you're missing

01

Anything can be a node

Blender on a GPU, a shared browser, your own API or model.

02

Two files, and Weft does the plumbing

Its inputs and outputs, plus the Rust that does the work. Credentials, storage and run history come free.

03

Plugged into everything

It wires to any node whose types fit, and the compiler checks its wiring rules.

04

Tested on its own

Against fakes on your machine, or live against the real service.

Nodes somebody built for their own job

Blender Render

render the scene on a GPU

GPU · own container
Browser Session

keep a browser open to share

live · others join
Pricing API

price the order with our rules

your API
Fraud Model

score the order with our model

your model
nodes/blender_render/ a folder, two files
metadata.jsonwhat it takes and gives back
mod.rswhat it does

▶ Folding

A hundred nodes still look like five: any group folds into one box

Cron Schedule

check for new leads every morning

qualify and contact each lead
HTTP Request

look up the lead's company

LLM

decide whether the lead fits

write, approve and send the email
LLM

draft the email to this lead

Human

approve or edit the draft

Send Email

send the email once it's approved

HTTP Request

log the result in the CRM

Visual builders turn to spaghetti past twenty nodes. Weft folds, so it stays readable at any size.

Use the arrows on a group’s header to fold it or open it.

▶ And more

Four more things Weft does today

terminal
$weft run outreach.wft
✓Type-checked 12 nodes, 14 edges
✓Built to native Rust
✓Infrastructure provisioned
✓Triggers listening
Running · waiting for events

Built on Rust: real speed, not a slow graph

Weft compiles the graph to native Rust. One command starts it as a live service.

Postgres: Database

store the program's data in Postgres

started for you

✓a Postgres container
✓a disk that survives restarts
✓pg.access, for the query and write nodes to plug into

Nodes that bring their own infrastructure

Write pg = PostgresDatabase and the program gets a Postgres of its own, with no YAML to write.

your machine

Docker

your cloud

Serverless

terminal
$weft target add prod https://weft.example.com
$weft login prod
$weft activate --on prod

From your machine to your own cloud

GCP now, AWS and Azure next

Serverless workers that cost nothing while idle and scale up when work arrives. Tangle sets up the rest once you log in to Google Cloud and GitHub.

Socket

carry the caller's audio both ways

Transcribe (Realtime)

turn speech into text live

LLM

decide what to say back

Speak (streaming)

read the answer aloud to the caller

Bus Communication
bus 7f3a · live call streaming
00:00* caller joined
00:02transcribe:"I need to reschedule my delivery"
00:02llm:looking up your order…
00:03speak:"Sure, what day works?"
00:05transcribe:"Friday"

Nodes that talk to each other, live

In a phone-call agent, speech-to-text, the model and the voice all share one live bus. Every message is visible and replayable.

▶ Pricing

Free and open source, Tangle included

Price

$0

No plans, no seats, no usage meter

Self-hosted Weft stays free.

Fund development

If Weft is running your automations in production, put something back: one-time tips and monthly support both go straight into the build.

Fund on Ko-fi

▶ Founder

Why I am building this

Quentin Feuillade--Montixi

Quentin Feuillade--Montixi

Founder & CEO

I'm a software and ML engineer by training. The day ChatGPT came out I went full time on prompting and doing research on llm behavior. I spent the last three years breaking AI for a living: for Anthropic, OpenAI, METR, etc. The more I learned about how these models behave, the more I wanted to work on the system around them instead of the model itself.

Everyone is racing to get AI to actually do things now: act, call tools, run real processes. And we hand all of that to one agent and hope it carries the whole job from start to finish. Models are not there yet, and I don't want to wait years for them to catch up before AI can take on long, real jobs reliably.

Having built software for years, the answer is obvious to me: we need something shaped like a program, but with the same magic as an agent. A company already works this way: it chases one goal for years, even though each person only handles their own part and people come and go. Weft does the same in code. No model has to carry the whole job, because the program does, and it keeps going for days if it has to. Each agent or model call only gets a short job, the kind today's models already do well, so this works now instead of in a few years. And it's cheaper and faster than handing everything to one agent.

I believe this is the shape we'll all be building in a year, and no one else is looking here yet as a language design problem. Programming languages have always been the foundation on which the evolution of software has been built, and I believe right now is the time to build the one that will support this next generation of software.

As flexible as an agent, as reliable as code

Free and open source · Write to me