# weft — full site text Generated from the HTML at weftgo.dev so it matches what readers see. Index: https://weftgo.dev/llms.txt --- *Source: https://weftgo.dev/* *Summary: Open-source Go framework for AI agents: tools are plain Go functions, every run is recorded with OpenTelemetry, and Studio replays any run from any step.* weft v0.14.2 (https://github.com/weftgo/weft/blob/main/CHANGELOG.md) · open source, MIT # The AI agent framework for Go. An open-source library you import into your own Go service. Write tools as plain Go functions; weft runs the agent loop, keeps the conversation, and records every run so you can inspect and replay it in Studio. Start building $go get github.com/weftgo/weft the api ## An API you already know. So does your coding agent. Everything an agent needs, in small, standard-shaped Go. 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 (https://pkg.go.dev/github.com/weftgo/weft). studio & devtools ## Iterate live, from any step. Open a run in Studio, or in the devtools panel beside your own app. Change what you want and run it again. Studio is one `http.Handler` in your app, or `weft dev` from the terminal. - See the runEvery step, tool call and the exact request the model got. - Change itThe prompt, a tool's arguments or result, or the model. - Replay and compareFrom that step, in your app, diffed against the original. Tools with side effects answer from the recording unless you opt them in. [image: 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. [image: 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. [image: 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. ### One command for the dev loop `weft dev` starts Studio on `127.0.0.1:7331` (or the next free port), runs your app beside it, and restarts it when you save a `.go` file. Apps in other languages send OpenTelemetry to the same port. ``` 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 ``` design & architecture ## How weft is built. One loop at the center, three optional layers on top, and nothing you can't see into. one call to `Generate`, step by step - Shaped like the standard library.Small interfaces, `context`, functional options, iterators. If you know `net/http`, you know weft. - A tool error is data; a run error is yours.A failed or panicking tool becomes a result the model reads. Only a failed run comes back to you as an error. - Nothing hidden.The vendors' official SDKs, standard OpenTelemetry with the GenAI semantic conventions, and no hosted service. - Pay for what you import.Layers only import downward, and only the packages you use are compiled in. `weft/core` is also its own module, and depends only on the OpenTelemetry API. for coding agents ## Easy for LLMs to write, too. Claude Code, Cursor and Copilot already know the patterns weft uses, and the docs are published in the form models read best. - AGENTS.mdThe whole API on one screen, in the repo root (https://github.com/weftgo/weft/blob/main/AGENTS.md). - llms.txt and llms-full.txtThis site as Markdown: llms.txt for the summary, llms-full.txt for everything. - Mistakes fail at compile timeFamiliar Go, typed tool inputs: a wrong field is a build error, not a bad run. `wefttest` lets the agent test what it built, offline. - Coming soon: a CLI, a skill and a promptAn agent-friendly `weft` CLI and a getting-started skill, so your coding agent can set up weft on its own. More below. paste into Claude Code, Cursor or Copilot ``` 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. ``` get started ## Your first agent in five minutes. ### Let your coding agent set it up coming soon Getting started with an LLM: ask Claude Code, Cursor or Copilot for a weft agent, and it does the steps below for you. - A weft CLI made for agentsThe `weft` command, with commands and output a coding agent can drive on its own: create a project, run it, check it, read its runs. - A getting-started skillInstall it in your coding agent. It knows the steps, the API and how to test what it builds with `wefttest`. - A starter promptOne prompt that takes an empty folder to a tested agent, with Studio open on every run. or by hand, today - ### Install go get github.com/weftgo/weft@v0.14.2 - ### Write a tool A Go function with a typed input struct. `weft.Tool` reflects its JSON Schema; `weft.New` makes the agent. - ### Run and watch weft dev Studio opens beside your app with every run recorded. 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 or drag-and-drop agent builder: weft is a library you write Go code against. Also when you 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. **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.