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.
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.
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.
The devtools panel docks beside your own chat page and follows the conversation live.
Every step, tool call and span, with subagents nested under the call that started them.
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.
Generate, step by step- Shaped like the standard library.Small interfaces,
context, functional options, iterators. If you knownet/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/coreis 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.
- 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.
wefttestlets the agent test what it built, offline. - Coming soon: a CLI, a skill and a promptAn agent-friendly
weftCLI 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 soonGetting 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
weftcommand, 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.2Write a tool
A Go function with a typed input struct.
weft.Toolreflects its JSON Schema;weft.Newmakes the agent.Run and watch
weft devStudio 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.