Help us shape the future of Go! Take the 2026 Go Developer Survey

runtime

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 1, 2026 License: MIT Imports: 24 Imported by: 0

Documentation

Overview

Package runtime is the playground's in-app side (WEFT-PLAYGROUND.md §10.2, [D6]): it registers the agents your code built with the Studio the app is already observed by, receives experiment commands over the runtime link, and executes them as real runs of those agents — your tools, your model keys, your process. Studio never runs your agent; it asks, this package answers.

The whole integration is one deferred call:

defer runtime.Install(
    runtime.Studio(url, token),            // or runtime.Local(srv) in setup A
    runtime.Agents(support, billing),      // the agents a runtime exposes
    runtime.Models(map[string]weft.Model{  // allowed alternates, by display name
        "glm-5.3-flash": glmFlash,
    }),
    runtime.Limits(runtime.Budget{MaxTokensPerExperiment: 200_000, MaxRunsPerExperiment: 60}),
    runtime.AllowSideEffects("lookup_order"),
    runtime.Threads(store),                // thread.Storage; nil = ephemeral only
)()

Safety (WEFT-PLAYGROUND.md §6, non-negotiable)

Without Install no link opens, and even then only when WEFT_ENV=dev or Enabled(true) is set — production binaries expose nothing unless they opt in explicitly. Commands can only narrow: tools the agent registered can be turned off, never added (OnlyTools); models come from the Models allow-list; MaxSteps and Parallelism only lower. Side effects never re-fire silently (§6 rule 3): a tool counts as "never" unless its code vouched weft.Replay(weft.ReplaySafe). In side_effects "substitute" (the default), a parked call that matches a recorded call of the source (same tool, same args) is answered with the recorded result — the runtime acts as ADR 0007's resolver, the handler never runs; a miss stays parked for a human (the panel's continue / skip / resolve). "park" keeps every side-effect call at the boundary; "allow" runs for real, but only tools the runtime opted in with AllowSideEffects. The debugger's breakpoints (§8.3) park their tools on every run this package starts, and steer (§8.4) delivers into a run it holds — the app's own turns are never breakable or steerable from here (D7, PQ7).

The engines: "live" runs the agent's own model (or a Models alternate); "scripted" (§5.5) answers each model call with the source run's recorded turn at zero tokens — its own weft.Model over the messages records, keyed like wefttest's fixtures and missing loudly ("no recorded turn") when the input changed, never silently answering a prompt experiment. Thread modes: "ephemeral" (nothing written to thread storage) and "fork" (§5.4) — the source session opens read-side, Fork copies it to a new session with lineage (thread mints the run ids, stamps weft.session.forked_from), and the command's input becomes the fork's next turn under the same shaping; a later fork command on the fork continues it in place.

Runs this package starts are ordinary weft runs: they flow through the weft/otel pipeline to every destination, carrying weft.playground = true, weft.playground.command, weft.experiment.id and weft.forked_from, and never weft.session.id in ephemeral mode (an experiment is not a turn of the session). Per-experiment budget caps (Limits) are counted from each command's own usage; a breach rejects the next command of that experiment and never touches the app's own runs.

Where it sits

A module of its own because it imports thread (fork mode, transcript reads) and carries an executor, a registry and budget accounting — none of which belongs in the exporter-wiring module weft/otel (review §1.8). Arrows point down only: this package imports root, thread, obsdb, otel and studio (studio for *studio.Server alone, in runtime.Local); nothing imports it back.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Install

func Install(opts ...Option) (shutdown func())

Install registers the agents with a Studio and starts the runtime link: it dials out (never listens), so it works behind NAT. It never panics and never fails the program — a runtime that cannot be built (nothing enabled, no endpoint, no named agents) logs a WARN and opens nothing. The returned function stops the link; call it on exit, like otel.Install's.

The link registers on connect and after every reconnect, receives commands over an SSE stream (resuming with Last-Event-ID), acks every command before executing it (at-most-once: a repeated command id is ignored), executes it as a run of the named agent, and reports the run's end with a finished ack. The run's content flows back through the normal OTel pipeline, not through the link.

Example

ExampleInstall is the whole integration: one deferred call in main. Enabled(false) keeps the example inert — in a real dev binary the link opens because WEFT_ENV=dev (or Enabled(true)).

package main

import (
	"fmt"

	"github.com/weftgo/weft"
	"github.com/weftgo/weft/runtime"
	"github.com/weftgo/weft/wefttest"
)

func main() {
	support := weft.New(
		wefttest.Script(wefttest.Say("Your order shipped yesterday.")),
		weft.Name("acme-support"),
	)
	glmFlash := wefttest.Script(wefttest.Say("…"))
	shutdown := runtime.Install(
		runtime.Studio("http://127.0.0.1:7331", ""),
		runtime.Agents(support),
		runtime.Models(map[string]weft.Model{"glm-5.3-flash": glmFlash}),
		runtime.Limits(runtime.Budget{MaxTokensPerExperiment: 200_000, MaxRunsPerExperiment: 60}),
		runtime.AllowSideEffects("lookup_order"),
		runtime.Enabled(false), // dev-only by default: WEFT_ENV=dev
	)
	defer shutdown()
	fmt.Println("link:", "closed")
}
Output:
link: closed

Types

type Budget

type Budget struct {
	MaxTokensPerExperiment int64 // input + output tokens
	MaxRunsPerExperiment   int64
}

Budget caps one experiment, counted per experiment_id from the usage of the commands this runtime ran (§6 rule 6). Zero fields are no caps. A breach rejects the *next* command of that experiment (budget_exceeded) — never a run in flight, never the app's own runs.

type Option

type Option func(*config)

Option configures Install.

func Agents

func Agents(agents ...*weft.Agent) Option

Agents registers the agents this runtime exposes. Only registered agents are playable (WEFT-PLAYGROUND.md §5.2). An agent without a name (weft.Name) cannot register — its manifest would be nameless — and is skipped with a WARN.

func AllowSideEffects

func AllowSideEffects(tools ...string) Option

AllowSideEffects names the tools whose handlers may really run for a playground command that asks for side_effects "allow". Every side-effect tool (ReplayPolicy never, the unannotated default) parks at the approval boundary in the other modes; a tool marked weft.Replay(weft.ReplaySafe) is not a side effect and may run in any mode.

func Enabled

func Enabled(on bool) Option

Enabled opens (or forbids) the link explicitly. The default — no Enabled option — is on only when WEFT_ENV=dev: production binaries expose the runtime link only by explicit opt-in (§6 rule 1).

func Limits

func Limits(b Budget) Option

Limits sets this runtime's per-experiment caps. Without it, a runtime accepts unlimited playground runs within the agent's own budgets (MaxSteps, UsageLimit).

func Local

func Local(srv *studio.Server) Option

Local takes the embedded Studio server (setup A): the link talks to srv's handler in-process, no socket. srv is the studio.New(...) server the app mounts; nil is ignored.

func Models

func Models(models map[string]weft.Model) Option

Models declares the model alternates a command may switch to, by display name — the allow-list the playground's model picker reads and the resolver that turns a command's model string back into a weft.Model (§5.2). A name missing here is refused: the playground cannot add a model, only choose among the ones the code registered.

func Studio

func Studio(url, token string) Option

Studio dials the Studio at url with token (setups B and C: the local binary or the hosted one). Empty token is the dev mode of setup B. Without a Studio or Local option, Install falls back to the pipeline's own Studio destination — otel.StudioEndpoint() — and opens nothing when the pipeline has none.

func Threads

func Threads(store thread.Storage) Option

Threads sets the thread.Storage transcript reads resolve through first (WEFT-PLAYGROUND.md §10.3): readers never lock, so an open session is readable. Without it the runtime is ephemeral-only and resolves transcripts from its local obsdb or from Studio. nil is ignored.

Directories

Path Synopsis
examples
local command
Command local is setup A's playground in one process: an embedded Studio on loopback, the app's own pipeline exporting into it, one agent with a scripted model and two tools, and the runtime link — WEFT-PLAYGROUND.md §7's P0 slice, drivable with curl.
Command local is setup A's playground in one process: an embedded Studio on loopback, the app's own pipeline exporting into it, one agent with a scripted model and two tools, and the runtime link — WEFT-PLAYGROUND.md §7's P0 slice, drivable with curl.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL