v0.14.2 · open source · MIT · Go 1.26+

AI agents in Go.
Batteries included.

Tools are plain Go functions. weft runs the loop, keeps the conversation, records every run, and lets you replay any of them.

$go get github.com/weftgo/weft@v0.14.2

OpenAI · Anthropic · Google · MCP · OpenAI-compatible servers

main.go · a complete agent
type Order struct {
    ID string `json:"id"`
}

func lookup(ctx context.Context,
    in Order) (string, error) {
    return db.Status(ctx, in.ID) // yours
}

func main() {
    defer otel.Install()() // record runs

    agt := weft.New(
        anthropic.Model("claude-sonnet-5"),
        weft.Tool("lookup_order",
            "Find an order.", lookup))

    res, _ := agt.Generate(ctx,
        weft.Prompt("Where is order 1042?"))
    fmt.Println(res.Text())
}

Order 1042 shipped this morning.2 steps · 1 tool call · recorded in ./.weft/weft.db

why weft

The agent loop is 40 lines. Production is everything else.

weft is built the way Go is built, and handles what breaks after the demo.

Reads like the standard library

Small interfaces, context, functional options, iterators. If you know net/http, you know weft.

weft.New(model, tools...)

Tools run in parallel

Calls fan out on goroutines. One failure goes back to the model as data; the others finish.

weft.Parallelism(8)

A human approves

A refund parks the run. A person decides over any channel, and the next run resumes.

weft.RequireApproval()

Sessions survive restarts

Every step is appended as it happens. Reopen after a crash and the conversation continues.

thread.Open(ctx, st, id, agt)

Every run is recorded

Standard OpenTelemetry into a local SQLite file, or Datadog, Langfuse and any OTLP endpoint.

defer otel.Install()()

Tests run offline

Script a model, or record a real one once and replay it in CI. Free and deterministic.

wefttest.Replay(t, "testdata")

the api

Everything an agent needs, in code you can already read.

Streaming is a range loop over typed events. Cancel with context; each stream ends with exactly one terminal error.

for ev, err := range agt.Stream(ctx, prompt).Events() {
    if err != nil {
        return err
    }
    switch ev := ev.(type) {
    case weft.TextDelta:
        io.WriteString(w, ev.Text)
    case weft.ToolStart:
        slog.Info("tool", "name", ev.Name)
    }
}

The final answer is decoded into a struct, on every provider. An invalid submission is a tool error the model fixes.

type Verdict struct {
    Approved bool   `json:"approved"`
    Reason   string `json:"reason"`
}

agt := weft.New(model, weft.Output[Verdict](), lookup)
v, res, err := weft.GenerateAs[Verdict](ctx, agt, prompt)

A gated call parks and the run ends with it pending. Resume with the decision; a denial is a result the model reads.

refund := weft.Tool("refund", "Refund an order.", doRefund,
    weft.RequireApproval())

res, _ := agt.Generate(ctx, weft.Prompt("Refund order 42"))
call := res.Pending[0] // ask someone: Slack, a UI, email

res, _ = agt.Generate(ctx, weft.Messages(res.Messages...),
    weft.Approve(call.ID))

A session is an append-only file. A crash mid-turn loses nothing; reopen it with the same agent.

st, _ := jsonl.Open(dir) // or thread/sqlite, thread.Memory()
s, _ := thread.Create(ctx, st, agt)

turn, _ := s.Send(ctx, weft.User("Where is order 1234?"))
res, _ := turn.Wait()

// after a restart: the same conversation
s, _ = thread.Open(ctx, st, id, agt)

A subagent is a tool. Its events nest in the parent's stream, its usage adds up, and its failure is data.

researcher := weft.New(model, searchTool)

orchestrator := weft.New(model,
    weft.Subagent("research", "Research in depth.",
        researcher, weft.Timeout(2*time.Minute)))

Agent tests run in go test with no network: a scripted model, or a real one recorded once.

model := wefttest.Script(
    wefttest.ToolCalls(wefttest.Call{
        Name: "lookup_order", Args: `{"id":"1042"}`}),
    wefttest.Say("Order 1042 has shipped."),
)

// or record a real model once, replay it forever
model = wefttest.Replay(t, "testdata/order")

Full reference on pkg.go.dev.

studio

See every run. Replay any step.

Studio is the UI on your recordings: one http.Handler in your app, or weft dev from the terminal.

An Acme Support chat page on the left with two order questions and their answers. On the right, the weft devtools panel docked beside it lists the conversation's two turns and shows the open turn: span timings, the lookup_order tool call with its arguments and result, the reply, and Experiment and Re-run buttons.

The devtools panel docks beside your own chat page and follows the conversation live.

Studio's run page: prompt and answer, the two steps (a lookup_order tool call, then the reply), a span waterfall with invoke_agent, chat and execute_tool spans, and the selected tool span's timing and attributes.

Every step, tool call and span, with subagents nested under the call that started them.

Studio's playground: variant B's settings on the left; on the right, variant A's result with a diff against the original turn, variant B's lookup_order call awaiting a continue or skip decision, and a table comparing status, tokens, latency and steps.

Edit the prompt, model or tools and compare variants. Side-effect tools are replayed or parked, never fired twice.

The exact request

Each model call's system prompt, tool catalog and parameters, recorded beside the transcript.

Replay from any step

Edit the transcript in place and preview the exact request before it is sent.

Step-aligned diff

Compare runs step by step: what the model saw, called and answered.

Search, cost, save as test

Full-text search, cost per run, and any run exported as wefttest fixtures.

One command for the dev loop

weft dev starts Studio on 127.0.0.1:7331, runs your app beside it, and restarts it on save. Apps in other languages send OpenTelemetry to the same port.

terminal
go install \
  github.com/weftgo/weft/cmd/weft@v0.14.2

weft dev            # Studio + your app
weft runs --failed  # find the bad run
weft doctor         # check the setup

architecture

One module. Four layers. Use only what you need.

Import weft for everything; only the packages you use are compiled in. Import weft/core for the loop alone.

github.com/weftgo/weft
weft/studio + runtime

See and replay any run: inspector, devtools panel, playground.

weft/otel + obsdb

Record every run as OpenTelemetry, into SQLite or ClickHouse.

weft/thread

Durable sessions: branching, compaction, approvals, steering.

own moduleweft/core

The loop: tools, parallel calls, streaming, approvals, subagents, MCP, providers. One dependency: the OpenTelemetry API.

Official vendor SDKs, standard OpenTelemetry, no hosted service. MCP works both ways: consume servers as tools, or expose your tools as one.

get started

Your first agent in five minutes.

  1. Install

    go get github.com/weftgo/weft@v0.14.2
  2. Write a tool

    A Go function with a typed input struct. weft.Tool reflects its JSON Schema; weft.New makes the agent.

  3. Run and watch

    weft dev

    Studio opens beside your app with every run recorded.

Using a coding agent?

The repo ships AGENTS.md, the whole API on one screen, and this site publishes llms.txt. Paste this into Claude Code, Cursor or Copilot:

prompt
Read https://weftgo.dev/llms-full.txt and https://github.com/weftgo/weft/blob/main/AGENTS.md. Build a Go agent with weft that answers support questions with a lookup_order tool, records every run, and serves Studio at /studio/. Test it with wefttest.

shipped · v0.14.2

Core, three providers, MCP, sessions, recording, Studio, replay and the weft command.

next

First-party HTTP/SSE serving, evals over recorded runs, a prompt registry.

then

Memory and durable-execution adapters, and a 1.0 core API behind a compatibility gate.

faq

Questions people ask.

What is weft?

weft is an open-source Go framework for building AI agents. Tools are plain Go functions; weft runs the agent loop, keeps durable sessions, records every run over OpenTelemetry, and ships Studio to inspect and replay any run. One Go module is the whole framework, and the loop alone is its own module. MIT licensed, Go 1.26+.

How do I get started with weft?

Run go get github.com/weftgo/weft@v0.14.2, write a tool as a Go function with a typed input struct, create an agent with weft.New(model, tools...), and call Generate. Add defer otel.Install()() to record runs, then run weft dev (or mount studio.Handler) to see them in Studio.

Which Go agent framework should I use?

For a Go service, weft: a standard-library-shaped API, the vendors' official SDKs for OpenAI, Anthropic and Google, MCP both ways, parallel tools on goroutines, human approvals, durable sessions, OpenTelemetry recording, Studio, and offline tests. It is modular, so you can adopt only the core.

When is weft not the right fit?

When you want a hosted no-code agent builder, want to write the agent itself in Python or TypeScript, need a graph engine today (weft's is designed, not shipped), or need a frozen 1.0 API now. Studio still works for agents in any language: it ingests OpenTelemetry.

Can I use weft if my backend is Python, TypeScript or Java?

Yes, as a service. The agent runs as a small Go program beside your backend, which calls it over HTTP, gRPC or a queue; Go compiles to one static binary. Studio also ingests OpenTelemetry from agents written in any language: run weft studio and point the exporter at 127.0.0.1:7331.

Which model providers does weft support?

OpenAI and any OpenAI-compatible server, Anthropic, and Google Gemini, through the vendors' official Go SDKs. MCP works both ways: consume MCP servers as tools, or expose your tools as an MCP server.

How do I see what my agent did?

Add defer otel.Install()() to record every event, transcript and span to a local SQLite file, then run weft dev or mount studio.Handler(studio.DB(otel.LocalDB())) in your HTTP mux. Studio shows each step, tool call, span and the exact request sent to the model. The same pipeline exports to Datadog, Langfuse or any OTLP endpoint.

Can I replay an agent run from the middle?

Yes. In Studio or the devtools panel, replay from any step, tool call or message, and edit the transcript first: the user message, a tool's arguments or result, or the reply. Studio previews the exact request the model will receive, and the step-aligned diff compares the replay with the original.

Is it safe to re-run a turn in the playground?

Yes. Experiments run in your process, and a tool that is not marked safe to re-run is answered from the recording or parked. Only the tools you opt in with runtime.AllowSideEffects run for real.

What is the weft command?

The weft binary (go install github.com/weftgo/weft/cmd/weft@v0.14.2) is the dev loop: weft dev runs Studio and your app together and restarts the app on save, weft studio serves Studio alone with OTLP ingest, weft runs lists runs, weft export turns a run into a wefttest fixture, and weft doctor checks the setup.

Can an AI coding assistant build with weft?

Yes. The repository ships AGENTS.md, which fits the whole API on one screen, and the site publishes llms.txt and llms-full.txt. The API follows the patterns models already know from net/http: small interfaces, context, functional options.

Is weft production ready?

weft is v0.14.2, pre-1.0. Every layer has been through a production-readiness review; the thread API and storage format are not frozen. Pin your versions, because breaking changes can still happen between minor releases.