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 ¶
- func Install(opts ...Option) (shutdown func())
- type Budget
- type Option
- func Agents(agents ...*weft.Agent) Option
- func AllowSideEffects(tools ...string) Option
- func Enabled(on bool) Option
- func Limits(b Budget) Option
- func Local(srv *studio.Server) Option
- func Models(models map[string]weft.Model) Option
- func Studio(url, token string) Option
- func Threads(store thread.Storage) Option
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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.
Source Files
¶
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. |