Claude
Skills
Sign in
Back

weft-ai-language

Included with Lifetime
$97 forever

Expert skill for building AI systems with Weft, a Rust-based programming language where LLMs, humans, APIs, and infrastructure are first-class primitives with typed connections and durable execution.

Backend & APIs

What this skill does


# Weft AI Language

> Skill by [ara.so](https://ara.so) — Daily 2026 Skills collection.

Weft is a programming language (implemented in Rust) for AI systems where LLMs, humans, APIs, databases, and agents are base language primitives. You wire nodes together, the compiler type-checks every connection, and the program runs with durable execution backed by Restate (survives crashes, supports multi-day human-in-the-loop pauses). A visual graph view is generated automatically from code.

---

## Installation & Setup

### Prerequisites

- Docker (for PostgreSQL)
- Node.js
- macOS: `brew install bash` (Bash 4+ required)
- Rust, Restate, and pnpm are auto-installed by `dev.sh`

### Clone and Configure

```bash
git clone https://github.com/WeaveMindAI/weft.git
cd weft
cp .env.example .env
# Edit .env — add your API keys
```

### Environment Variables (`.env`)

```bash
OPENROUTER_API_KEY=     # Required for LLM nodes
TAVILY_API_KEY=         # Required for Web Search nodes
ELEVENLABS_API_KEY=     # Required for Speech-to-Text nodes
APOLLO_API_KEY=         # Required for Apollo enrichment nodes
DISCORD_BOT_TOKEN=      # Required for Discord nodes
```

All keys are optional at startup — missing keys surface as runtime errors only when the relevant node executes.

### Start Development

```bash
# Terminal 1 — backend (PostgreSQL, Restate, all services)
./dev.sh server

# Terminal 2 — dashboard (SvelteKit at http://localhost:5173)
./dev.sh dashboard

# Or both at once
./dev.sh all
```

### VS Code

Use the **Dev Local All** task to start server + dashboard in split terminals.

---

## Development Commands

```bash
./dev.sh server               # Start backend services
./dev.sh dashboard            # Start frontend
./dev.sh all                  # Start everything
./dev.sh extension            # Build browser extension

./cleanup.sh                  # Stop everything, wipe Restate + DB
./cleanup.sh --no-db          # Stop services, keep database
./cleanup.sh --services       # Stop services only
./cleanup.sh --db-destroy     # Remove PostgreSQL container entirely

cargo build                   # Build without running PostgreSQL (uses .sqlx snapshots)
cargo test                    # Test without running PostgreSQL
```

### Infrastructure Nodes (Kubernetes)

Only needed if using nodes like Postgres Database that provision K8s resources:

```bash
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.31.0/kind-$(uname -s | tr '[:upper:]' '[:lower:]')-amd64
chmod +x ./kind && sudo mv ./kind /usr/local/bin/kind

INFRASTRUCTURE_TARGET=local ./dev.sh server
```

---

## The Weft Language

### Core Concepts

- **Nodes** — typed computational units (LLM, HTTP, Human Query, Gate, etc.)
- **Connections** — typed edges between node ports; compiler validates all types
- **Groups** — collapse any set of nodes into a single reusable node
- **Durable execution** — programs checkpoint via Restate; long pauses are transparent

### Node Syntax

```weft
node_name = NodeType -> (output_port: OutputType) {
  label: "Human-readable name"
  config_key: "value"
}
node_name.input_port = other_node.output_port
```

### Simple Example — Poem Generator

```weft
# Project: Poem Generator
# Description: Writes a short poem about any topic

topic = Text {
  label: "Topic"
  value: "the silence between stars"
}

llm_config = LlmConfig {
  label: "Config"
  model: "anthropic/claude-sonnet-4.6"
  systemPrompt: "Write a short, beautiful poem (4-6 lines) about the given topic."
  temperature: "0.8"
}

poet = LlmInference -> (response: String) {
  label: "Poet"
}
poet.prompt = topic.value
poet.config = llm_config.config

output = Debug { label: "Poem" }
output.data = poet.response
```

---

## Built-in Node Catalog

### AI Nodes
| Node | Purpose |
|---|---|
| `LlmConfig` | Configure model, system prompt, temperature |
| `LlmInference` | Call an LLM, returns `response: String` |

### Data Nodes
| Node | Purpose |
|---|---|
| `Text` | Static or dynamic text value |
| `Number` | Numeric value |
| `Dict` | Key-value map |
| `List` | Ordered list |
| `Pack` / `Unpack` | Bundle/unbundle multiple values |

### Flow Nodes
| Node | Purpose |
|---|---|
| `Gate` | Conditional branching |
| `HumanQuery` | Pause execution, send form to human, resume on response |
| `HumanTrigger` | Start a program from a human action |

### Communication Nodes
`Discord`, `Slack`, `Telegram`, `WhatsApp`, `Email`, `X`

### Storage Nodes
`Postgres`, `Memory`

### Enrichment Nodes
`Apollo`, `WebSearch`, `SpeechToText`

### Trigger Nodes
`Cron`, webhooks, polling

### Utility Nodes
`Debug`, `Template`, `HTTP`, `Code` (Python execution)

---

## Common Patterns

### Pattern 1 — LLM with Structured Config

```weft
# Project: Content Summarizer
# Description: Summarizes a webpage given a URL

url_input = Text {
  label: "URL"
  value: "https://example.com/article"
}

search = WebSearch -> (results: String) {
  label: "Fetch Content"
}
search.query = url_input.value

summarizer_config = LlmConfig {
  label: "Summarizer Config"
  model: "anthropic/claude-sonnet-4.6"
  systemPrompt: "Summarize the following content in 3 bullet points."
  temperature: "0.3"
}

summarizer = LlmInference -> (response: String) {
  label: "Summarizer"
}
summarizer.prompt = search.results
summarizer.config = summarizer_config.config

output = Debug { label: "Summary" }
output.data = summarizer.response
```

### Pattern 2 — Human-in-the-Loop Approval

```weft
# Project: Content Approval Pipeline
# Description: AI drafts content, human approves before publishing

draft_config = LlmConfig {
  label: "Drafter Config"
  model: "openai/gpt-4o"
  systemPrompt: "Write a Twitter thread about the given topic. Be engaging."
  temperature: "0.7"
}

topic = Text {
  label: "Topic"
  value: "distributed systems"
}

drafter = LlmInference -> (response: String) {
  label: "Content Drafter"
}
drafter.prompt = topic.value
drafter.config = draft_config.config

# Pauses execution indefinitely until a human responds
approval = HumanQuery -> (approved: Boolean, feedback: String) {
  label: "Human Approval"
  question: "Do you approve this draft for publishing?"
}
approval.content = drafter.response

gate = Gate -> (passed: String) {
  label: "Approval Gate"
}
gate.condition = approval.approved
gate.value = drafter.response

publisher = Discord {
  label: "Publish to Discord"
  channel: "announcements"
}
publisher.message = gate.passed
```

### Pattern 3 — Conditional Branching with Gate

```weft
# Project: Sentiment Router
# Description: Routes messages based on sentiment analysis

message = Text {
  label: "Input Message"
  value: "This product is absolutely terrible!"
}

sentiment_config = LlmConfig {
  label: "Sentiment Config"
  model: "anthropic/claude-haiku-3.5"
  systemPrompt: "Classify sentiment as 'positive' or 'negative'. Respond with one word only."
  temperature: "0.0"
}

classifier = LlmInference -> (response: String) {
  label: "Sentiment Classifier"
}
classifier.prompt = message.value
classifier.config = sentiment_config.config

is_negative = Gate -> (passed: String) {
  label: "Is Negative?"
}
is_negative.condition = classifier.response
is_negative.value = message.value

alert = Slack {
  label: "Alert Team"
  channel: "customer-issues"
}
alert.message = is_negative.passed
```

### Pattern 4 — Cron-Triggered Pipeline

```weft
# Project: Daily Digest
# Description: Sends a daily news digest every morning

schedule = Cron {
  label: "Daily Trigger"
  expression: "0 8 * * *"
}

news = WebSearch -> (results: String) {
  label: "Fetch News"
}
news.query = "AI and technology news today"

digest_config = LlmConfig {
  label: "Digest Config"
  model: "openai/gpt-4o-mini"
  systemPrompt: "Summarize these news items into a concise morning digest."
  temperature: "0.4"
}

digest = LlmInference -> (response: String) {
  label: "Digest Writer"
}
digest.prompt = news.results
digest.config = digest_config.config

send = Email {
  label: "Send Digest"
  to: "[email protected]"
  subject: "Your

Related in Backend & APIs