adaptor

package module
v1.1.2 Latest Latest
Warning

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

Go to latest
Published: Aug 7, 2026 License: Apache-2.0 Imports: 30 Imported by: 0

README

agent-adaptor

简体中文 | 日本語 | 한국어 | Deutsch

agent-adaptor is an SDK that offers a small, intuitive API for driving different agent flavors — Codex, Claude Code, Cursor, CodeBuddy — through one interface, plus a range of capabilities beyond plain invocation.

agent := adaptor.New(codex.Driver(codex.Config{Model: "gpt-5.6-sol"}))
result, err := agent.Run(ctx, "Fix the failing tests")

Switching to Claude Code only means swapping the Driver in the constructor; the rest of your code stays untouched.

Capability overview

  • Unified configuration: one API controls skills, MCP, system prompts, models, sandboxing, tools, and approvals across agents.
  • Streaming responses: optional streaming output that distinguishes reasoning, text output, tool calls, and decision requests as the scenario requires.
  • Conversation management: seamless continuation and forking. Use your own business ID (a ticket number, a user ID) as the conversation key without dealing with the underlying session bookkeeping.
  • Human decisions: answer questions, intercept dangerous commands, and confirm plans through callbacks or events. A built-in decision write-back mechanism lets decisions be persisted in the cloud rather than only in the local process.

Advanced features

  • Structured output: define a Go struct, call RunAs[T], and the agent runs under a constraint that returns a populated object.
  • Multi-protocol decoration: built-in A2A/AGUI decoration turns an Agent into a standard agent with SSE + AGUI streaming in one line, so a custom front end or client is all you need for a complete agent service (a runnable CopilotKit front end is included).
  • Multi Agent: cross-Driver team agents — for example Codex as the leader agent autonomously coordinating a Plan Agent (Codex), a Coding Agent (Claude), and a Reviewer Agent (Cursor), with all progress and output aggregated into the leader's event stream (see the examples/showcases/team-agent-workflow showcase).
  • Agent isolation: copy the machine's agent configuration and login state into a dedicated directory so changes never affect the agent you use locally. Running several Codex/Claude Code instances in parallel for concurrent development or different roles becomes trivial.

Install

go get github.com/agent-dance/agent-adaptor

Requires Go 1.26.5 or later.

Important: the matching agent CLI must already be installed and authenticated at run time.

Quick start

package main

import (
	"context"
	"fmt"
	"log"

	adaptor "github.com/agent-dance/agent-adaptor"
	"github.com/agent-dance/agent-adaptor/codex"
)

func main() {
	agent := adaptor.New(
		codex.Driver(codex.Config{Model: "gpt-5.4"}),
		adaptor.WithWorkspace("/path/to/repository"),
	)

	result, err := agent.Run(context.Background(), "Fix the failing tests")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(result.Text)
}

The four built-in Drivers are constructed the same way, each with its own Config:

codexAgent := adaptor.New(codex.Driver(codex.Config{}))
claudeAgent := adaptor.New(claude.Driver(claude.Config{}))
cursorAgent := adaptor.New(cursor.Driver(cursor.Config{}))
codeBuddyAgent := adaptor.New(codebuddy.Driver(codebuddy.Config{}))

Streaming execution

Stream unfolds one invocation into a single strongly typed event stream and yields a Result at the end:

stream := agent.Stream(ctx, "Explain the patch that is about to be committed")
defer stream.Cancel()

for event := range stream.Events() {
	switch event := event.(type) {
	case adaptor.TextDelta:
		fmt.Print(event.Text)
	case adaptor.Thinking:
		fmt.Fprint(os.Stderr, event.Text)
	case adaptor.ToolCall:
		if event.Phase == adaptor.PhaseStart {
			fmt.Printf("\n[tool call: %s]\n", event.Name)
		}
	case *adaptor.ApprovalRequest:
		_ = event.Approve(ctx)
	case adaptor.Dropped:
		log.Printf("backpressure dropped %d incremental events", event.Count)
	}
}

result, err := stream.Result()

Text, reasoning, tool calls and their results, process information, lifecycle, subagent progress, and approval requests all travel on this one stream. There is no second channel.

Call Cancel() when you stop consuming early; it is idempotent.

Human approval and sandboxing

Sandbox strength, network and browser tools, and approval modes live in the same Policy. The constructor sets defaults, and Run / Stream can override the whole policy per call:

reviewer := adaptor.New(
	claude.Driver(claude.Config{}),
	adaptor.WithPolicy(adaptor.Policy{
		Sandbox:   adaptor.ReadOnly,    // read-only workspace, suited to review and planning roles
		WebSearch: adaptor.FeatureDeny, // explicitly disable web search
		Browser:   adaptor.FeatureDeny,
		Approvals: adaptor.ApprovalPolicy{
			Permission: adaptor.ApprovalAsk, // hand dangerous commands to a human
			PlanReview: adaptor.ApprovalAsk,
			Question:   adaptor.QuestionAsk, // questions are auto-denied by default
			Timeout:    2 * time.Minute,
			OnTimeout:  adaptor.FallbackAbort,
		},
	}),
)

The sandbox has three levels — ReadOnly, WorkspaceWrite, Unrestricted — and presets such as PolicyReadOnly are just shortcuts that set Sandbox alone. When the selected Driver does not support one of these dimensions, you get an explicit error before the process starts instead of a silent downgrade.

Approvals have two consumption shapes; pick one. Attaching a callback gives you the callback shape, which suits CLIs and unattended runs:

agent := adaptor.New(
	claude.Driver(claude.Config{}),
	adaptor.OnApproval(func(ctx context.Context, req *adaptor.ApprovalRequest) error {
		switch req.Kind {
		case adaptor.ApprovalPermission:
			return req.Approve(ctx)
		case adaptor.ApprovalQuestion:
			return req.Answer(ctx, "Use PostgreSQL")
		default:
			return req.Deny(ctx, "the plan needs human confirmation")
		}
	}),
)

For unattended runs, adaptor.ApproveAll() and adaptor.DenyAll(reason) are ready to use.

Without a callback you get the event shape: the request arrives on the event stream as an *adaptor.ApprovalRequest carrying its own responder, so it can be parked and later resolved by any goroutine or by another HTTP request — exactly what web scenarios need:

for event := range stream.Events() {
	switch event := event.(type) {
	case *adaptor.ApprovalRequest:
		pending.Add(threadKey, event) // park the request and push it to the front end
	case adaptor.Notice:
		// The SDK broadcasts every settled decision, including policy auto-approvals
		// and timeout fallbacks, so the host never has to reconcile its pending list.
		if event.Kind == adaptor.NoticeApprovalResolved {
			if id, ok := event.Data["request_id"].(string); ok {
				pending.Remove(threadKey, id)
			}
		}
	}
}

pending is the host's own storage; once the front end has the request, it resolves the decision in a separate HTTP request:

func (h *host) resolveDecision(w http.ResponseWriter, r *http.Request) {
	req := h.pending.Take(threadKey, requestID)
	if err := req.Approve(r.Context()); err != nil {
		sse.WriteApprovalError(w, err) // already resolved or expired → 410, Kind mismatch → 400
		return
	}
	w.WriteHeader(http.StatusNoContent)
}

Responses are exactly-once: duplicate responses, Kind mismatches, and finished runs all return stable errors (ErrApprovalResolved, ErrApprovalKindMismatch, ErrApprovalExpired), and a zero-value request never blocks forever. When nobody answers, OnTimeout from Policy.Approvals takes over; a rejection follows OnReject. Where parked requests live is up to the host and is not limited to process memory.

A complete, runnable web HITL path is in web-chat/copilotkit: two endpoints, /decision/pending and /decision/resolve, with pending decisions surviving a page refresh.

Multi-turn conversations

Agents are stateless by default. When you need conversation continuity, inject a store:

agent := adaptor.New(
	claude.Driver(claude.Config{}),
	adaptor.WithThreadStore(memory.NewStore()),
)
defer agent.Close(context.Background())

thread := agent.Thread("tenant-42/issue-123")        // continue the mapped conversation if it exists, otherwise create it
result, err := thread.Run(ctx, "Keep investigating this problem")

only := agent.Thread("tenant-42/issue-123", adaptor.ResumeOnly()) // resume only, never create
branch := thread.Fork("tenant-42/issue-123/plan-b")               // fork from the current progress

A few conventions:

  • The conversation key is the host's own string; the SDK stores and compares it verbatim. Start a brand-new conversation with a new key — the SDK offers no entry point for rebinding an old key to a new conversation.
  • One Thread runs at most one invocation at a time, guaranteed by a lease, so an expired run never overwrites newer state.
  • Compatibility is checked before resuming: the Driver, model, resolved workspace, configuration, skills, and MCP all feed the fingerprint, and drift in any one of them prevents an incorrect conversation reuse.
  • Failures do not pollute state: non-zero exits, protocol errors, and cancellations produce no valid checkpoint, so the previously healthy conversation record stays as it was.
  • Persistent processes are reused by default: on Windows, macOS, and Linux, Claude, CodeBuddy, and Codex reuse one process across turns of an explicit Thread. Add adaptor.WithSpawn() when one turn or every turn needs a fresh process. Cursor and stateless calls always start a new process per turn. Runs after Close return ErrAgentClosed.

Use memory.NewStore() for single-process scenarios; implement threadstore.Store when you need durability.

Structured output

type ReleasePlan struct {
	Filename  string `json:"filename"`
	MediaType string `json:"media_type"`
	Summary   string `json:"summary"`
	Content   string `json:"content"`
}

plan, result, err := adaptor.RunAs[ReleasePlan](ctx, agent,
	"Produce the release plan as a Markdown file artifact.")
if err != nil {
	return err
}
fmt.Printf("%s (%s)\n%s\n", plan.Filename, result.RunID, plan.Content)

The schema is derived from the Go type and prefers each provider's native schema enforcement. When the current transport or policy does not support it, execution falls back to prompt constraints plus local validation automatically; only when neither is available does the run fail before starting. The return values include both the typed value and the full audit Result.

For details, see the structured-output example and the structured output documentation.

Options and resources

Options share one vocabulary, and their scope is separated by type at compile time:

Type Where it applies
Option adaptor.New only
CallOption Run / Stream only
SharedOption Both; the call site overrides the constructor

There is a single merge rule: the nearer value wins, skills append, and everything else replaces or merges according to its own contract.

The same set of options covers the main configuration surface of every agent:

What you want to control What to use
Model WithModel
System prompt WithInstructions
Working directory WithWorkspace, or WithWorkspaceSpec for isolated work trees
skills WithSkills with skill.Dir / skill.FS / skill.Inline / skill.Key / skill.Require
MCP WithMCP with mcp.Stdio / mcp.HTTP / mcp.SSE
Sandbox, network, browser tools, approvals WithPolicy, plus OnApproval when interactive
Configuration directory and resources WithProfile, WithProfileResources
Timeout, audit metadata, caller identity WithTimeout, WithMetadata, WithIdentity
Conversation persistence WithThreadStore
agent := adaptor.New(
	codex.Driver(codex.Config{}),
	adaptor.WithModel("gpt-5.4"),
	adaptor.WithInstructions("You are this repository's reviewer: read the code only, state the conclusion before the evidence."),
	adaptor.WithSkills(skill.Dir("./skills/review")),
	adaptor.WithMCP(mcp.Stdio("repo-tools", "repo-mcp", mcp.Args("serve"))),
	adaptor.WithProfile(profile.Dedicated("./profiles/reviewer")),
	adaptor.WithTimeout(10*time.Minute),
)

result, err := agent.Run(ctx, "Review this change",
	adaptor.WithModel("gpt-5.4-mini"),
	adaptor.WithSkills(skill.Require(skill.Dir("./skills/security"), "this run must pass the security review")), // appends, does not displace the default skills
	adaptor.WithMetadata("request_id", requestID),
)

The same configuration with a different Driver is a different Agent; when a Driver does not support one of the capabilities, you get an explicit error before startup rather than a silent omission.

codexReviewer := adaptor.New(codex.Driver(codex.Config{}), reviewerOptions...)
claudeReviewer := adaptor.New(claude.Driver(claude.Config{}), reviewerOptions...)

Host-defined Tools

Extend an Agent with typed Go functions directly, without constructing or maintaining an MCP server yourself:

type SearchInput struct {
	Query string `json:"query" jsonschema:"required"`
}

type SearchOutput struct {
	Files []string `json:"files"`
}

searchRepo := tool.Define(
	"search_repo",
	"Search files in the current repository.",
	func(ctx context.Context, in SearchInput) (SearchOutput, error) {
		return search(ctx, in.Query)
	},
	tool.ReadOnly(),
	tool.Idempotent(),
	tool.Revision("search_repo/v1"),
)

agent := adaptor.New(
	codex.Driver(codex.Config{}),
	adaptor.WithTools(searchRepo),
)
defer agent.Close(context.Background())

WithTools is construction-only and replaces the Tool set as a whole. Schemas are inferred from the handler's Go types by default, and an explicit standard JSON Schema can be supplied instead. tool.Reject(code, message) reports a business failure that is safe to show the model; only package-minted rejections pass that boundary, while ordinary errors, lookalikes, and panics are sanitized. Every Tool used by a stateful Thread needs a tool.Revision so that changes in handler behavior participate in resume compatibility.

MCP is only the internal delivery mechanism here: existing or remote MCP servers still go through WithMCP, and built-in Drivers materialize Tools into an SDK-owned isolated profile, leaving the native profile you configured untouched. Each Agent receives an unpredictable bearer-token environment-variable name, and another MCP server cannot alias that credential carrier. For lifecycle, schema, error, security, and Thread semantics see the host-defined Tools contract.

Agent isolation

WithProfile decides which provider configuration directory an Agent uses. profile.CloneNative clones an independent profile from the machine's native configuration and can optionally bring along settings, MCP, and skills; the login state is shared through a link instead of copying tokens:

worker := adaptor.New(
	claude.Driver(claude.Config{}),
	adaptor.WithProfile(profile.CloneNative("/var/agents/worker-1",
		profile.CopySettings(),
		profile.CopyMCP(),
		profile.CopySkills(),
		profile.LinkAuth(), // share the machine's login state via a symlink, so local re-logins are picked up automatically
	)),
)

One CLI can therefore run several instances in parallel, per role or per task, with configuration changes isolated from each other and from the ~/.claude and ~/.codex you use locally:

isolated := func(dir string) adaptor.Option {
	return adaptor.WithProfile(profile.CloneNative(dir,
		profile.CopySettings(), profile.LinkAuth()))
}

planner := adaptor.New(codex.Driver(codex.Config{}),
	isolated("/var/agents/planner"),
	adaptor.WithPolicy(adaptor.PolicyReadOnly),
)
implementer := adaptor.New(claude.Driver(claude.Config{}),
	isolated("/var/agents/implementer"),
	adaptor.WithWorkspace("/repo/worktrees/feature-x"),
)

Three other choices exist: profile.Native() uses the machine's native configuration directly; profile.Dedicated(dir) pins a directory you manage yourself; profile.CloneFrom(src, dst, ...) derives from a template directory. A profile participates in the conversation fingerprint, so it can only be a construction option and cannot be switched per call.

To see what declared resources actually materialized and whether the Driver truly accepts them, read with agent.ProfileState(ctx) and materialize with agent.SyncProfile(ctx); both report only what was actually observed. See the profiles example for a full walkthrough.

Results and errors

Success returns *Result, nil. Failure travels only through Go's error: a run that completed but failed on the business level returns a *RunError carrying whatever Result is available, while infrastructure failures are ordinary wrappable errors.

result, err := agent.Run(ctx, prompt)
if err != nil {
	var runErr *adaptor.RunError
	if errors.As(err, &runErr) {
		log.Printf("run failed: %s; available summary: %s", runErr.Reason, runErr.Result.Summary)
	}
	return err
}

Each output layer of Result stays free of the others:

Field Contents
Text The final user-facing answer text
Summary A short summary suited to lists, logs, and issue comments
Raw() Complete stdout and stderr, plus each provider's official terminal payload
Transcript() Normalized entries the Driver parsed from the official protocol
Services() Runtime services actually observed during this run
Decode() Validated structured output
Usage / Model / Provider / Metadata Usage and audit information

Text never mixes in raw stdout, and it never automatically appends the summary or a provider's terminal payload. What you get from Run and from Stream.Result() is field-for-field equivalent.

Integrating into applications

Web front ends: one line wraps an Agent into an http.Handler speaking the AG-UI protocol, so AG-UI compatible clients (such as CopilotKit) can connect directly:

mux.Handle("/agent", sse.Handler(agent, sse.Options{
	Protocol: sse.AGUI,
}))

A2A: bridges/a2a publishes any Runner as an A2A server, leaving routing, authentication, and TLS to the host:

server := bridgea2a.NewServer(agent, bridgea2a.ServerOptions{
	AgentCard: bridgea2a.AgentCard{
		Name:        "Local coding agent",
		Description: "Runs coding tasks through agent-adaptor",
		Version:     "1.0.0",
		URL:         "https://host.example/a2a",
	},
	Session: bridgea2a.ThreadByContextID(), // the remote contextID maps stably to a local Thread key
	Options: []adaptor.CallOption{adaptor.WithPolicy(adaptor.PolicyWorkspaceWrite)},
})

mux.Handle("/.well-known/agent-card.json", server.AgentCardHandler())
mux.Handle("/a2a", server.Handler())

Use clients/a2a to call a remote A2A agent. It returns A2A tasks, messages, and artifacts, and never pretends that a remote protocol task has a local CLI's stdout or Result:

client := clienta2a.New(clienta2a.Options{
	AgentCardURL: "https://remote.example/.well-known/agent-card.json",
	Auth:         clienta2a.BearerTokenFromEnv("REMOTE_A2A_TOKEN"),
})
defer client.Close()

task, err := client.Send(ctx, clienta2a.SendRequest{
	Message: clienta2a.Message{
		Role:  "user",
		Parts: []clienta2a.Part{{Kind: clienta2a.PartText, Text: "Review this change"}},
	},
})

Use SendStream / Subscribe when you need the intermediate steps. Whether reasoning, tool calls, approval events, or diagnostic fields are exposed outward is controlled by ExposurePolicy, which defaults to minimal exposure.

Multi-agent collaboration

agent-adaptor supports cross-Driver multi-agent collaboration over the standard A2A protocol (which therefore also covers any remote A2A agent).

The value of cross-Driver collaboration is preserving the fit between a model and its native Harness: GPT models perform better on Codex, and Claude models are stronger in Claude Code. agent-adaptor is therefore designed to let each model collaborate from the harness that suits it best, rather than settling for one generic harness that supports many models but performs poorly just to enable multi-model collaboration.

The core code looks like this:

team, err := a2adelegation.NewService(a2adelegation.Config{
	Agents: []a2adelegation.AgentRef{
		a2adelegation.LocalNamed("plan", "Codex Planner", planner, a2adelegation.Policy{}),
		a2adelegation.LocalNamed("impl", "Claude Code Implementer", implementer, a2adelegation.Policy{}),
		a2adelegation.LocalNamed("review", "Codex Reviewer", reviewer, a2adelegation.Policy{}),
	},
})
if err != nil {
	return err
}
defer team.Close()

leader := adaptor.New(leaderDriver, team.Option())
stream := leader.Stream(ctx, "Plan, implement, and review TASK.md")
for event := range stream.Events() {
	if update, ok := event.(adaptor.SubagentUpdate); ok {
		fmt.Printf("[%s] %s: %s\n", update.Agent, update.Kind, update.Delta)
	}
}

The complete team-agent-workflow adds role-level sandboxes, a structured PLAN.md artifact, workspace auditing, and a CopilotKit page with live subagent cards, all started with one command:

./examples/showcases/team-agent-workflow/start-all.sh claude

Environment probes

Agent.Inspect() is a read-only probe used for preflight checks, environment diagnostics, and model selection. Unsupported probes report unsupported explicitly instead of inventing data:

environment, err := agent.Inspect().Environment(ctx) // health status and per-item diagnostics, ready to render
models, err := agent.Inspect().Models(ctx)
quota, err := agent.Inspect().Quota(ctx)
state, err := agent.ProfileState(ctx)                // reports desired versus observed only, changes nothing
synced, err := agent.SyncProfile(ctx)                // explicitly materializes configuration resources

Six nouns

The library's entire public model consists of six nouns:

Noun Meaning
Agent A fully configured agent, ready to run once constructed
Thread A conversation identified by a host key, resumable and forkable
Stream One invocation in progress
Event One strongly typed occurrence during an invocation
Result The final result and audit information of one invocation
Driver An integration for one agent CLI, relevant only to extension authors

The accompanying constraints are: one constructor, one option merge rule, one execution pipeline, one event stream, and one failure verdict.

Packages

Package Purpose
driver The Driver SPI, used when integrating a new agent
codex, claude, cursor, codebuddy Built-in Drivers and their Config types
tool, skill, mcp, profile Consumer-facing capability and resource vocabularies
threadstore, memory The Thread persistence contract and its in-memory implementation
bridges SSE, AG-UI, A2A, and subagent-stream protocol bridges
clients/a2a The A2A client
hosttools Optional delegation orchestration and event recording components
adaptertest The Driver conformance suite

To integrate your own agent CLI: implement driver.Driver, get adaptertest passing, and from then on it has the same higher-level capabilities as the built-in Drivers.

Examples

  • quickstart: construct an Agent and run one prompt.
  • streaming: event consumption and cancellation.
  • threads: continuation, resume-only, forking, and checkpoint auditing.
  • structured-output: typed JSON output.
  • tools: expose a typed Go function to a real local provider without managing MCP yourself.
  • skills / profiles: skill resolution and materialization, configuration resources, and synchronization.
  • inspect: environment, models, quota, schema, skills, and profile state.
  • web-chat: an SSE/AG-UI server with two front ends, aguiclient and copilotkit.
  • a2a-server: publish and call an Agent through A2A.
  • showcases/team-agent-workflow: planning, implementation, and review joined into one pipeline.

Examples that make real calls depend on the corresponding CLI and its login state. The repository's ordinary tests never produce paid calls.

Boundaries

The core library does not provide an HTTP/gRPC server, queue, scheduler, multi-tenancy, authorization, or database, and it does not decide which agent a task should be dispatched to. Protocol serving belongs to bridges and host applications; team roles and workflow policy belong to the host.

Documentation

License

Unless otherwise noted, this repository is licensed under the Apache License, Version 2.0. Third-party material retains its own license and attribution; see Third-Party Notices.

Codex, Claude, Cursor, CodeBuddy, and other product names are trademarks of their respective owners. They are used only to identify supported integrations; this project is not affiliated with or endorsed by those owners.

Documentation

Overview

Package adaptor provides one API for running local coding agents.

The API is organized around six nouns:

  • Agent is a configured, ready-to-run driver plus host defaults.
  • Thread adds durable resume and fork semantics to an Agent.
  • Stream represents one execution in progress.
  • Event is one typed observation from that execution.
  • Result is its final output and audit record.
  • Driver is the provider integration SPI implemented in package driver.

Construct an Agent directly from a provider Driver. Multiple agents are ordinary Go variables; the package has no central SDK object or registry:

agent := adaptor.New(
	codex.Driver(codex.Config{Model: "gpt-5.4"}),
	adaptor.WithWorkspace("/repo"),
)
result, err := agent.Run(ctx, "Review this change")

Run and Stream share one execution pipeline. Run is exactly Stream followed by draining Events and calling Result. Agent and Thread both implement Runner, so bridges and host integrations do not need separate stateful and stateless paths.

On Windows, macOS, and Linux, built-in Drivers reuse one provider process across compatible Thread turns by default when the provider supports it. WithSpawn forces a fresh process for an Agent default or one call, and Agent.Close performs bounded, idempotent cleanup of processes owned by that Agent.

Options have explicit scopes. Option applies at construction, CallOption applies to one invocation, and SharedOption may be used in either place. Per-call values override Agent defaults; skills append, while other settings follow their documented replacement or merge rules.

Host-defined Tools use the provider-neutral tool package and the construction-only WithTools option. The Agent owns their runtime for its full lifetime; MCP delivery, authentication, and endpoint lifecycle remain internal implementation details. Existing external MCP servers continue to use WithMCP.

An Agent is stateless unless constructed with a ThreadStore. Agent.Thread continues or creates the host key, while Thread.Fork creates an independent child. The SDK coordinates leases, compatibility fingerprints, and atomic checkpoint persistence; provider resume identifiers remain Driver details.

Stream exposes one ordered typed Event channel. ApprovalRequest events carry their own exactly-once responder, allowing either callbacks or interactive hosts to approve, deny, or answer. Result separates assistant Text and Summary from Raw process streams, Transcript entries, runtime Services, and validated structured output. Business failures use RunError and retain the partial Result; infrastructure failures remain ordinary wrapped errors.

Index

Constants

View Source
const (
	// ProcessSpawn reports child-process launch details.
	ProcessSpawn = "spawn"
	// ProcessStdout carries a raw stdout chunk.
	ProcessStdout = "stdout"
	// ProcessStderr carries a raw stderr chunk.
	ProcessStderr = "stderr"
)

ProcessInfo kinds.

View Source
const (
	// NoticeInvocation describes the resolved invocation metadata.
	NoticeInvocation = "invocation"
	// NoticeLifecycle reports high-level run lifecycle markers and
	// SDK warnings (for example the approval-retry degradation warning,
	// Data["warning"] == "human_decision_retry_unsupported").
	NoticeLifecycle = "lifecycle"
	// NoticeRuntime reports runtime-service preparation or cleanup.
	NoticeRuntime = "runtime"
	// NoticeStep marks a provider-defined work step boundary
	// (StreamKinds step.started / step.finished); Data["phase"] is
	// "started" or "finished" and Text carries the step name.
	NoticeStep = "step"
	// NoticeTranscriptItem carries one progressively parsed transcript
	// item. Item holds the normalized entry; the
	// complete ordered transcript remains available via Result.Transcript().
	NoticeTranscriptItem = "transcript.item"
	// NoticeApprovalRequested broadcasts that an approval request was
	// routed to a callback handler or auto-resolved by policy (in event
	// form the *ApprovalRequest event itself is the request signal).
	NoticeApprovalRequested = "approval.requested"
	// NoticeApprovalResolved broadcasts the final outcome of an approval
	// request (Data: request_id / kind / result / choice / attempt).
	NoticeApprovalResolved = "approval.resolved"
)

Notice kinds.

Variables

View Source
var (
	// ErrApprovalResolved is returned by Approve / Deny / Answer when the
	// request was already resolved — by an earlier response, by the
	// timeout fallback, or because the run ended.
	ErrApprovalResolved = errors.New("adaptor: approval request already resolved")
	// ErrApprovalKindMismatch is returned when the response method does
	// not fit the request kind: Approve on a Question, or Answer on a
	// Permission / PlanReview request.
	ErrApprovalKindMismatch = errors.New("adaptor: response does not match approval kind")
	// ErrApprovalUnavailable is returned by a nil, zero-valued, or otherwise
	// unbound request. Such values have no run-owned responder and therefore
	// can never be answered.
	ErrApprovalUnavailable = errors.New("adaptor: approval responder unavailable")
	// ErrApprovalExpired identifies a request whose response window or owning
	// run ended. It wraps ErrApprovalResolved so callers can treat every late
	// response as an already-resolved request while still detecting expiry.
	ErrApprovalExpired = fmt.Errorf("%w: request expired", ErrApprovalResolved)
)

Approval response errors.

View Source
var (
	// ErrAgentClosed is returned by an Agent or any Thread derived from it
	// after Agent.Close has begun.
	ErrAgentClosed = errors.New("adaptor: agent closed")
	// ErrApprovalDenied matches runs that failed because a human decision
	// was rejected.
	ErrApprovalDenied = errors.New("adaptor: approval denied")
	// ErrApprovalTimeout matches runs that failed because a human decision
	// timed out.
	ErrApprovalTimeout = errors.New("adaptor: approval timed out")
	// ErrAgentFailed matches driver-classified agent failures.
	ErrAgentFailed = errors.New("adaptor: agent failed")
	// ErrRunCancelled matches driver-classified cancellation failures.
	ErrRunCancelled = errors.New("adaptor: run cancelled")
	// ErrPolicyViolation matches policy validation failures.
	ErrPolicyViolation = errors.New("adaptor: policy violation")
)

Sentinels for errors.Is matching. Each RunError unwraps to the sentinel matching its Reason.

View Source
var (
	// ErrSkillNotFound: a bare skill key was requested (WithSkills /
	// SelectSkills) but the SkillProvider did not return it.
	ErrSkillNotFound = skill.ErrSkillNotFound
	// ErrSkillKeyConflict: two skill candidates share a key but differ
	// structurally. Unwrap to *SkillKeyConflictError for the sources.
	ErrSkillKeyConflict = skill.ErrSkillKeyConflict
	// ErrSkillMaterializationFailed: staging a skill's source to disk
	// failed. Unwrap to *SkillMaterializationError for the key.
	ErrSkillMaterializationFailed = skill.ErrSkillMaterializationFailed
	// ErrSkillSourceMissing: a skill declares no usable source.
	ErrSkillSourceMissing = skill.ErrSkillSourceMissing
	// ErrSkillKeyMissing: a concrete skill declaration has an empty key.
	ErrSkillKeyMissing = skill.ErrSkillKeyMissing
	// ErrInvalidMCPConfig: an MCP server spec is malformed (missing key,
	// transport/field mismatch, duplicate key).
	ErrInvalidMCPConfig = mcp.ErrInvalidConfig
	// ErrMCPUnsupported: the driver does not support MCP servers at all.
	ErrMCPUnsupported = mcp.ErrUnsupported
	// ErrMCPTransportUnsupported: the driver supports MCP but not this
	// server's transport.
	ErrMCPTransportUnsupported = mcp.ErrTransportUnsupported
	// ErrInvalidOutputSchema: the structured-output schema is invalid or
	// could not be derived. Unwrap to *InvalidOutputSchemaError.
	ErrInvalidOutputSchema = driver.ErrInvalidOutputSchema
	// ErrStructuredOutputUnsupported: the driver's capability matrix
	// cannot honor structured output through either supported mechanism.
	// Unwrap to *StructuredOutputUnsupportedError for Driver diagnostics.
	ErrStructuredOutputUnsupported = driver.ErrStructuredOutputUnsupported
	// ErrInvalidDriverConfig: Driver.ValidateConfig rejected the Driver's
	// captured construction-time configuration before launch.
	ErrInvalidDriverConfig = driver.ErrInvalidDriverConfig
	// ErrInvalidPolicy: a Policy field contains an out-of-domain value.
	ErrInvalidPolicy = driver.ErrInvalidPolicy
	// ErrPolicyCapabilityUnsupported: a valid, explicitly selected Sandbox,
	// WebSearch, or Browser value is unsupported by the Driver.
	ErrPolicyCapabilityUnsupported = driver.ErrPolicyCapabilityUnsupported
	// ErrHumanDecisionModeUnsupported: an explicitly selected approval mode
	// is not advertised by the Driver's RunPolicyCaps.
	ErrHumanDecisionModeUnsupported = driver.ErrHumanDecisionModeUnsupported
)
View Source
var (
	// PolicyReadOnly is a read-only workspace policy (reviewers, planners).
	PolicyReadOnly = Policy{Sandbox: ReadOnly}
	// PolicyWorkspaceWrite allows writes inside the resolved workspace.
	PolicyWorkspaceWrite = Policy{Sandbox: WorkspaceWrite}
	// PolicyUnrestricted requests the driver's full-access sandbox.
	PolicyUnrestricted = Policy{Sandbox: Unrestricted}
)

Common sandbox presets. Configure human-in-the-loop behavior independently through Policy.Approvals or an OnApproval handler.

View Source
var (
	// ErrThreadStoreRequired: the agent has no threadstore.Store
	// (WithThreadStore) but a Thread run or Checkpoint was requested.
	ErrThreadStoreRequired = errors.New("adaptor: thread store required (use WithThreadStore)")
	// ErrThreadNotFound: a resume-only thread (or a fork parent) has no
	// stored conversation under its key.
	ErrThreadNotFound = errors.New("adaptor: thread not found")
	// ErrThreadBusy: another run holds the thread's exclusivity lease
	// right now; retry after it finishes.
	ErrThreadBusy = errors.New("adaptor: thread busy")
	// ErrThreadIncompatible: the stored conversation no longer matches the
	// current configured Driver, identity, model, resolved workspace,
	// profile/skill/MCP/instructions, or runtime-service environment, and
	// the thread is resume-only, so silently starting over is not allowed.
	ErrThreadIncompatible = errors.New("adaptor: thread incompatible with current configuration")
	// ErrThreadLeaseLost: the run lost its exclusivity lease mid-flight
	// (store outage or takeover); its state was not persisted.
	ErrThreadLeaseLost = errors.New("adaptor: thread lease lost")
	// ErrThreadCheckpointMissing: the driver finished without producing a
	// resumable checkpoint, so the thread state could not be persisted.
	ErrThreadCheckpointMissing = errors.New("adaptor: driver returned no resumable checkpoint")
	// ErrThreadAlreadyExists: Fork's target key already has an active
	// conversation. The parent and existing target remain unchanged.
	ErrThreadAlreadyExists = errors.New("adaptor: thread already exists")
	// ErrResumeRejected: the driver refused to resume from the stored
	// checkpoint and the thread mode does not allow a fresh start.
	ErrResumeRejected = errors.New("adaptor: driver rejected thread resume")
)

Session-coordination failures are infrastructure errors: plain wrapped errors without a Result, classified by sentinel so hosts can branch with errors.Is.

View Source
var ApprovalsAutoDeny = ApprovalPolicy{
	Permission: driver.HumanDecisionAutoReject,
	PlanReview: driver.HumanDecisionAutoReject,
	Question:   driver.QuestionAutoReject,
}

ApprovalsAutoDeny is the ApprovalPolicy preset that explicitly denies every approval kind without asking. The bound Driver must advertise AutoReject for all three kinds; use a zero ApprovalPolicy for the portable conservative defaults when that capability is unavailable.

Functions

This section is empty.

Types

type Agent

type Agent struct {
	// contains filtered or unexported fields
}

Agent is a configured, ready-to-talk agent: one driver plus agent-level default settings. Construct with New; multiple agents are multiple Go variables (there is no central SDK object or named registry).

func New

func New(d driver.Driver, opts ...Option) *Agent

New constructs an Agent from a driver and agent-level default options. It is the single construction entry point for built-in and third-party drivers alike.

New panics when d is nil: a nil driver is a programmer error best caught at startup, not on the first Run.

func (*Agent) Close

func (a *Agent) Close(ctx context.Context) error

Close prevents new runs, cancels and drains admitted runs, closes every persistent provider process owned by the configured Driver, then closes the Agent-owned Tool runtime. It is idempotent; concurrent callers wait for the first close attempt or return ctx.Err() when their own deadline wins. Drivers without persistent-process support skip the process-close phase.

func (*Agent) Inspect

func (a *Agent) Inspect() Inspector

Inspect returns the inspection panel for this agent.

func (*Agent) ProfileState

func (a *Agent) ProfileState(ctx context.Context) (ProfileSnapshot, error)

ProfileState reports the desired vs observed profile resource state without changing anything. Drivers that implement the profile resource extension answer authoritatively; for everyone else the SDK builds the snapshot from the desired payload and reports non-skill resources as desired-but-not-observed (synced=false) — the truthful-materialization contract.

func (*Agent) Run

func (a *Agent) Run(ctx context.Context, prompt string, opts ...CallOption) (*Result, error)

Run executes one prompt to completion and returns the Result. It is Stream + drain + Result() — there is no separate batch execution path. Run consumes the same unified event pipeline and discards the events. Approvals still work through the OnApproval callback; without a handler, an "ask" approval times out into the Policy.Approvals fallback, since Run has no event consumer to answer it.

Per-call options override the agent defaults for this invocation only ("nearer scope wins; skills append, everything else replaces"); the agent defaults are never mutated, so concurrent and successive runs do not pollute each other.

Business failures return *RunError carrying the full Result; infrastructure failures (context cancellation/deadline, process crash, protocol breakage) return plain wrapped errors. Both travel the single err path.

func (*Agent) SelectSkills

func (a *Agent) SelectSkills(ctx context.Context, keys []string) (SkillSnapshot, error)

SelectSkills installs a process-local skill selection override: the given keys replace the agent-default refs for every subsequent Run/Stream/Thread resolution and Inspect().Skills report, until the next SelectSkills call. Keys must reference skills visible through the SkillProvider or the inline defaults (bare-key selection semantics — inline Skill values can only be introduced via WithSkills); unknown keys fail with ErrSkillNotFound and the override is NOT installed. The resolved selection is synced to the driver before the override takes effect.

func (*Agent) Stream

func (a *Agent) Stream(ctx context.Context, prompt string, opts ...CallOption) Stream

Stream starts one prompt and returns the live Stream immediately. Options merge exactly like Run ("nearer scope wins; skills append, everything else replaces"); the agent defaults are never mutated.

Stream never returns an error: startup failures surface through the normal contract (closed Events channel + Result() error).

func (*Agent) SyncProfile

func (a *Agent) SyncProfile(ctx context.Context) (ProfileSnapshot, error)

SyncProfile pushes the desired profile resources to the driver and reports the resulting state. Drivers with the profile resource extension perform the full sync; for everyone else the SDK syncs the one portable resource (skills, via the driver's skill support) and reports the rest as not-materialized errors (synced=true) rather than pretending they applied.

func (*Agent) Thread

func (a *Agent) Thread(key string, opts ...ThreadOption) *Thread

Thread returns the conversation handle for key, continuing the stored conversation when one exists and starting fresh otherwise (continue-or-start). key is the host's own opaque business string and is stored and compared verbatim.

Runs require a store injected via WithThreadStore; without one they fail with ErrThreadStoreRequired. Thread panics on an empty key (programmer error, symmetric with New's nil-driver panic).

type AgentProfile

type AgentProfile = driver.AgentProfile

AgentProfile is the driver-local profile report.

type AgentSettings

type AgentSettings struct {
	// RunSettings contains the defaults inherited by each invocation.
	RunSettings
	// contains filtered or unexported fields
}

AgentSettings = RunSettings (dual-scope fields) + construction-scope-only fields. The subset relation is expressed by struct embedding: a CallOption receives *RunSettings, on which the construction-only fields simply do not exist — the writable field set is the scope boundary.

func (*AgentSettings) SetBlockingEvents

func (s *AgentSettings) SetBlockingEvents()

SetBlockingEvents switches event delivery to blocking (no-drop) mode.

func (*AgentSettings) SetEventBuffer

func (s *AgentSettings) SetEventBuffer(n int)

SetEventBuffer sets the per-run ordinary-event buffer size. Terminal delivery uses separate internal reserve capacity.

func (*AgentSettings) SetProfile

func (s *AgentSettings) SetProfile(sel profile.Selection)

SetProfile replaces the driver-native profile selection.

func (*AgentSettings) SetServiceManager

func (s *AgentSettings) SetServiceManager(m ServiceManager)

SetServiceManager injects the runtime-service orchestration backend.

func (*AgentSettings) SetSkillMaterializer

func (s *AgentSettings) SetSkillMaterializer(m SkillMaterializer)

SetSkillMaterializer overrides the skill materialization strategy.

func (*AgentSettings) SetSkillProvider

func (s *AgentSettings) SetSkillProvider(p SkillProvider)

SetSkillProvider injects the skill provider used to resolve bare keys.

func (*AgentSettings) SetThreadStore

func (s *AgentSettings) SetThreadStore(store threadstore.Store)

SetThreadStore injects the thread storage backend (stateful conversations).

func (*AgentSettings) SetWorkspaceManager

func (s *AgentSettings) SetWorkspaceManager(m WorkspaceManager)

SetWorkspaceManager injects the workspace provisioning backend.

type ApprovalHandler

type ApprovalHandler func(ctx context.Context, req *ApprovalRequest) error

ApprovalHandler is the callback form (form A) of approval consumption, installed with OnApproval. The handler must resolve the request — call Approve, Deny, or Answer — and return nil, or return an error to abort the run.

func ApproveAll

func ApproveAll() ApprovalHandler

ApproveAll returns a ready-made handler that approves every Permission and PlanReview request. Questions are denied: they have no legitimate synthesized answer.

func DenyAll

func DenyAll(reason string) ApprovalHandler

DenyAll returns a ready-made handler that denies every request with the given reason.

type ApprovalKind

type ApprovalKind string

ApprovalKind labels the semantic category of an approval request.

const (
	// ApprovalPermission covers tool, command, file, or permission gates.
	ApprovalPermission ApprovalKind = ApprovalKind(driver.HumanDecisionPermission)
	// ApprovalPlanReview covers plan-mode approval before execution.
	ApprovalPlanReview ApprovalKind = ApprovalKind(driver.HumanDecisionPlanReview)
	// ApprovalQuestion covers structured clarification questions.
	ApprovalQuestion ApprovalKind = ApprovalKind(driver.HumanDecisionQuestion)
)

type ApprovalMode

type ApprovalMode = driver.HumanDecisionMode

ApprovalMode routes one binary approval kind (Permission / PlanReview).

const (
	// ApprovalInherit falls back to the SDK default (ask).
	ApprovalInherit ApprovalMode = driver.HumanDecisionUnset
	// ApprovalAsk routes the request to the host (callback or event form).
	ApprovalAsk ApprovalMode = driver.HumanDecisionAsk
	// ApprovalAutoApprove approves without asking (driver bypass path).
	ApprovalAutoApprove ApprovalMode = driver.HumanDecisionAutoApprove
	// ApprovalAutoDeny denies without asking.
	ApprovalAutoDeny ApprovalMode = driver.HumanDecisionAutoReject
)

type ApprovalPolicy

type ApprovalPolicy = driver.HumanDecisionPolicy

ApprovalPolicy carries the timeout / fallback / retry knobs for approval requests, plus the per-kind routing modes. It aliases the driver SPI HumanDecisionPolicy. Zero-valued fields inherit the package defaults (Permission/PlanReview ask, Question auto-deny, 30s timeout, abort on timeout/reject, 3 max retries).

type ApprovalRequest

type ApprovalRequest struct {

	// ID identifies this request (unique per run, fresh per retry).
	ID string
	// RunID is the SDK execution identifier of the owning run.
	RunID string
	// Kind is the request category; it gates which responder methods apply.
	Kind ApprovalKind
	// Title is the human-readable prompt to display.
	Title string
	// Source names the requesting surface (tool name, plan stage, ...).
	Source string

	// ToolCallID correlates a Permission request with the tool call that
	// triggered it (permission field group).
	ToolCallID string

	// Choices are the renderable options of a Question request (question
	// field group). Answer accepts one of the choice keys or free text.
	Choices []Choice

	// Details carries driver-specific structured request data.
	Details map[string]any

	// CreatedAt is when the current approval attempt was created.
	CreatedAt time.Time
	// Deadline bounds the response window; after it the ApprovalPolicy
	// OnTimeout fallback applies.
	Deadline time.Time

	// Attempt is the zero-based retry attempt (FallbackRetry re-asks).
	Attempt int
	// contains filtered or unexported fields
}

ApprovalRequest is a human-in-the-loop request that carries its own responder. It arrives either through the OnApproval callback (form A) or as a *ApprovalRequest event on the Stream (form B); in both forms exactly one of Approve / Deny / Answer resolves it. Late or duplicate responses return ErrApprovalResolved; if nobody responds before Deadline, the ApprovalPolicy timeout fallback applies.

func (*ApprovalRequest) Answer

func (r *ApprovalRequest) Answer(_ context.Context, option string) error

Answer resolves a Question request with the chosen option: one of the Choices keys, or free text for open questions. Calling it on a Permission / PlanReview request returns ErrApprovalKindMismatch.

func (*ApprovalRequest) Approve

func (r *ApprovalRequest) Approve(_ context.Context) error

Approve resolves a Permission or PlanReview request positively. Calling it on a Question returns ErrApprovalKindMismatch; calling it after the request was resolved returns ErrApprovalResolved.

func (*ApprovalRequest) Deny

func (r *ApprovalRequest) Deny(_ context.Context, reason string) error

Deny resolves any request kind negatively with a reason. What happens next is the ApprovalPolicy OnReject fallback (abort by default).

func (ApprovalRequest) Meta

func (c ApprovalRequest) Meta() EventMeta

type CallOption

type CallOption interface {
	// ApplyRun writes the option into this call's effective settings.
	ApplyRun(*RunSettings)
}

CallOption is the set Run/Stream accept. It writes the effective settings of one invocation (a clone of the agent defaults).

CallOption intentionally does NOT embed Option: call-scope-only options passed to New fail to compile too ("missing method ApplyNew"), keeping the misuse feedback symmetric in both directions.

func WithSchema

func WithSchema[T any](opts ...SchemaOption) CallOption

WithSchema requests structured output matching Go type T for this invocation. The JSON Schema document is derived from T at option construction time; a derivation failure fails the run before the driver launches (schema bugs are programmer errors, never silent degradation). The SDK always prefers native enforcement and automatically falls back to prompt validation. The default invalid policy fails the run.

Call scope only — passing WithSchema to New is a compile error ("missing method ApplyNew"): a schema belongs to one question, not to the Agent.

func WithSchemaJSON

func WithSchemaJSON(schemaJSON []byte, opts ...SchemaOption) CallOption

WithSchemaJSON requests structured output matching a raw JSON Schema document — the escape hatch for schemas that do not originate from a Go type (contract files, registry-served schemas). Generation-side SchemaOptions (SchemaInlineReferences, ...) have no effect here; the request-side ones (SchemaName / SchemaDescription / SchemaReturnInvalid) apply as usual. Call scope only.

type Checkpoint

type Checkpoint = driver.Checkpoint

Checkpoint is the driver resume handle exposed for audit purposes. It aliases the driver SPI checkpoint so hosts can inspect it without importing the SPI package.

type Choice

type Choice = driver.DecisionChoice

Choice is a single renderable option attached to an ApprovalQuestion request. It aliases the driver SPI type.

type ConfigSchema

type ConfigSchema = driver.ConfigSchema

ConfigSchema describes the driver's configuration surface.

type Driver

type Driver = driver.Driver

Driver is the provider integration SPI implemented by built-in and third-party agent integrations. It aliases the driver package interface so hosts can reference the type (struct fields, function signatures) without importing the SPI package.

type DriverManagedWorkspace

type DriverManagedWorkspace struct{}

DriverManagedWorkspace lets the Driver choose or create its own workspace according to its native behavior.

type Dropped

type Dropped struct {

	// Count is how many events were dropped since the previous marker.
	Count int
	// ByKind breaks Count down by the public event kind.
	ByKind map[string]int
	// FirstSequence is the first sequence number reserved for a discarded event.
	FirstSequence uint64
	// LastSequence is the last sequence number reserved for a discarded event.
	LastSequence uint64
	// Reason explains why events were lost.
	Reason string
	// Source identifies the component that reported the loss.
	Source string
	// Details preserves additional loss-report fields.
	Details map[string]any
	// contains filtered or unexported fields
}

Dropped is the aggregated backpressure marker: under the default drop strategy, events discarded because the consumer was slow are counted and surfaced as one Dropped event as soon as the channel has room again. See WithEventBuffer / WithBlockingEvents.

func (Dropped) Meta

func (c Dropped) Meta() EventMeta

type EnvironmentCheck

type EnvironmentCheck = driver.EnvironmentCheck

EnvironmentCheck is a single environment check line item.

type EnvironmentReport

type EnvironmentReport = driver.EnvironmentReport

EnvironmentReport is the result of an environment health check.

type Event

type Event interface {

	// Meta returns the SDK-owned event envelope. Sequence and Time describe
	// the order in which the unified sink accepted events, not a provider's
	// protocol cursor. Provider values, when present, remain in Source.
	Meta() EventMeta
	// contains filtered or unexported methods
}

Event is the sealed interface implemented by every stream event type.

The interface is sealed (unexported method): the set of event types is an SDK contract, exhaustively listed in this file. Consumers dispatch with a type switch:

for ev := range stream.Events() {
    switch e := ev.(type) {
    case adaptor.TextDelta:        io.WriteString(w, e.Text)
    case adaptor.ToolCall:         renderToolCard(e.Name, e.Args)
    case adaptor.Thinking:         renderReasoning(e.Text)
    case *adaptor.ApprovalRequest: _ = e.Approve(ctx)
    }
}

func WithEventMeta

func WithEventMeta(ev Event, meta EventMeta) Event

WithEventMeta returns ev with meta restored on a value copy. It is the narrow replay hook for bridges and persistent event recorders, whose wire envelope stores EventMeta separately from the typed event payload. A live run's sink always overwrites restored coordinates with its own authoritative run order before publication.

type EventMeta

type EventMeta struct {
	// RunID is the package-assigned execution identifier.
	RunID string
	// ThreadKey is the host's opaque Thread key, or empty for an Agent run.
	ThreadKey string
	// Sequence is the authoritative receive order within the run.
	Sequence uint64
	// Time is when the unified event sink accepted the event.
	Time time.Time
	// TurnID identifies a provider turn when the protocol exposes one.
	TurnID string
	// Source preserves provider envelope coordinates, when available.
	Source *EventSourceMeta
}

EventMeta is the common, SDK-owned envelope carried by every Event. Sequence is strictly increasing for one run and is assigned while the event sink serializes producers. ThreadKey is the host's opaque key; a provider thread/session identifier, if any, is kept in Source.ThreadID.

type EventSourceMeta

type EventSourceMeta struct {
	// RunID is the provider-reported run identifier.
	RunID string
	// ThreadID is the provider-reported conversation identifier.
	ThreadID string
	// TurnID is the provider-reported turn identifier.
	TurnID string
	// Sequence is the provider-reported event sequence.
	Sequence uint64
	// Timestamp is the provider-reported event time.
	Timestamp time.Time
}

EventSourceMeta preserves provider/driver envelope coordinates without allowing them to compete with the SDK's authoritative EventMeta fields.

type FailureReason

type FailureReason string

FailureReason classifies a business-level run failure.

const (
	// ReasonApprovalDenied means an approval was denied, including an
	// automatically denied request.
	ReasonApprovalDenied FailureReason = "approval_denied"
	// ReasonApprovalTimeout means an approval deadline elapsed.
	ReasonApprovalTimeout FailureReason = "approval_timeout"
	// ReasonAgentError: the driver classified an agent-level failure
	// (bad protocol, non-zero exit, handler panic, ...).
	ReasonAgentError FailureReason = "agent_error"
	// ReasonCancelled: the run was cancelled after producing a classified
	// business failure (as opposed to a bare context cancellation, which
	// surfaces as a plain error wrapping ctx.Err()).
	ReasonCancelled FailureReason = "cancelled"
	// ReasonPolicyViolation means policy validation failed.
	ReasonPolicyViolation FailureReason = "policy_violation"
)

type FallbackAction

type FallbackAction = driver.FailureAction

FallbackAction selects what happens when an approval times out (ApprovalPolicy.OnTimeout) or is denied (ApprovalPolicy.OnReject).

const (
	// FallbackInherit falls back to the SDK default (abort).
	FallbackInherit FallbackAction = driver.FailureActionUnset
	// FallbackAbort terminates the run with a business failure.
	FallbackAbort FallbackAction = driver.FailureAbort
	// FallbackContinue forwards the outcome to the agent so the run can
	// progress.
	FallbackContinue FallbackAction = driver.FailureContinue
	// FallbackRetry re-asks the same decision, bounded by MaxRetries;
	// drivers without retry support degrade to abort with a warning
	// Notice on the stream.
	FallbackRetry FallbackAction = driver.FailureRetry
)

type FeatureLevel

type FeatureLevel = driver.FeatureLevel

FeatureLevel gates optional capabilities (web search, browser tooling).

const (
	// FeatureInherit leaves the capability to the agent default or the
	// driver's own fallback.
	FeatureInherit FeatureLevel = driver.FeatureInherit
	// FeatureAllow explicitly enables the capability when supported.
	FeatureAllow FeatureLevel = driver.FeatureAllow
	// FeatureDeny explicitly disables the capability.
	FeatureDeny FeatureLevel = driver.FeatureDeny
)

type GitWorktreeWorkspace

type GitWorktreeWorkspace struct {
	// BaseRef is the git revision from which the worktree is created.
	BaseRef string
	// BranchTemplate is the host-defined template for naming a worktree branch.
	BranchTemplate string
	// WorktreeParentDir is the directory under which worktrees are created.
	WorktreeParentDir string
}

GitWorktreeWorkspace requests an isolated git worktree for the run.

type HumanDecisionModeUnsupportedError

type HumanDecisionModeUnsupportedError = driver.HumanDecisionModeUnsupportedError

HumanDecisionModeUnsupportedError reports the rejected kind, mode, and Driver capability matrix.

type Identity

type Identity struct {
	// ID is the logical agent identifier.
	ID string
	// Tenant partitions catalogues and stores by tenant.
	Tenant string
	// Profile partitions user-private resources within a tenant.
	Profile string
	// Name is the logical agent display name.
	Name string
}

Identity is host-supplied caller identity propagated into SDK hooks and the driver request. The SDK does not use these fields for routing; they exist so host-provided components (SkillProvider, WorkspaceManager, ServiceManager) can scope lookups without inventing their own context keys.

func IdentityFromContext

func IdentityFromContext(ctx context.Context) (Identity, bool)

IdentityFromContext returns the Identity the SDK injected into ctx before invoking provider hooks or the driver. Implementations that need scoping (Tenant for catalogue partitioning, Profile for user-private skills, ...) read it via this helper. The boolean is false when ctx carries no identity (e.g. a provider invoked directly in tests without SDK plumbing).

type Inspector

type Inspector struct {
	// contains filtered or unexported fields
}

Inspector is the read-only inspection panel of one Agent, obtained via Agent.Inspect(). Every method degrades honestly when the driver does not implement the corresponding probe: a descriptor-derived or explicitly "unsupported" report, never a fabricated success.

func (Inspector) ConfigSchema

func (in Inspector) ConfigSchema(ctx context.Context) (*ConfigSchema, error)

ConfigSchema returns the driver's configuration schema (driver.ConfigSchemaProvider), falling back to the descriptor's static schema. The returned schema is a copy.

func (Inspector) Environment

func (in Inspector) Environment(ctx context.Context) (EnvironmentReport, error)

Environment runs the driver's environment health check (driver.EnvironmentProbe). Drivers without the probe report a single informational "noop" check — visible, not invented.

func (Inspector) Models

func (in Inspector) Models(ctx context.Context) ([]ModelInfo, error)

Models lists the models the agent can run (driver.ModelLister). Drivers without the prober fall back to the static descriptor model list.

func (Inspector) Quota

func (in Inspector) Quota(ctx context.Context) (QuotaReport, error)

Quota reports live quota/billing state (driver.QuotaProbe). Drivers without the probe report Available=false with an explanatory error string.

func (Inspector) Skills

func (in Inspector) Skills(ctx context.Context) (SkillSnapshot, error)

Skills resolves and reports the agent's effective skill set: the default refs (or the SelectSkills override when one is active) resolved against the provider, with the inline defaults + the provider catalogue as non-selected candidates. The snapshot's sync mode reports truthfully whether the Driver can observe installed skills through driver.SkillSupport or the SDK only knows the desired set.

type InvalidDriverConfigError

type InvalidDriverConfigError = driver.InvalidDriverConfigError

InvalidDriverConfigError reports a rejected captured Driver config.

type InvalidOutputSchemaError

type InvalidOutputSchemaError = driver.InvalidOutputSchemaError

InvalidOutputSchemaError reports an invalid or underivable schema.

type InvalidPolicyError

type InvalidPolicyError = driver.InvalidPolicyError

InvalidPolicyError reports one out-of-domain Policy field.

type ModelInfo

type ModelInfo = driver.ModelInfo

ModelInfo describes one model the agent can run.

type Notice

type Notice struct {

	// Kind is one of the Notice* constants (unknown driver-specific kinds
	// pass through verbatim so no information is lost).
	Kind string
	// Text is the human-readable message.
	Text string
	// Item is the transcript entry (NoticeTranscriptItem only).
	Item *TranscriptItem
	// Metadata carries short string tags from the driver.
	Metadata map[string]string
	// Data carries structured details.
	Data map[string]any
	// contains filtered or unexported fields
}

Notice is a low-frequency operational event: invocation metadata, lifecycle markers, runtime-service reports, progressive transcript items, and approval lifecycle broadcasts. Consumers that do not care simply omit the case.

func (Notice) Meta

func (c Notice) Meta() EventMeta

type Option

type Option interface {
	// ApplyNew writes the option into the agent-level default settings.
	ApplyNew(*AgentSettings)
}

Option is the full set New accepts. It writes agent-level defaults.

Passing an Option-only value (WithThreadStore, WithEventBuffer, ...) to Run/Stream does not compile: "adaptor.Option does not implement adaptor.CallOption (missing method ApplyRun)" means the option is construction-scope only.

func WithBlockingEvents

func WithBlockingEvents() Option

WithBlockingEvents switches ordinary event delivery from the default drop-with-marker strategy to blocking: during normal execution EmitStream and Emit wait for the consumer and do not drop events. Cancel still releases blocked producers and may abandon pending ordinary events; the terminal event remains reserved. Construction scope only.

func WithEventBuffer

func WithEventBuffer(n int) Option

WithEventBuffer sets the per-run ordinary-event buffer size used by the streaming pipeline (default 1024). The SDK keeps separate internal capacity for the terminal event, so RunFinished remains deliverable when cancellation occurs while the ordinary buffer is full. When the consumer falls behind and the ordinary buffer fills, droppable events are surfaced as one aggregated Dropped{Count} marker. Construction scope only.

func WithProfile

func WithProfile(sel profile.Selection) Option

WithProfile selects the driver-native profile strategy (profile.Native / profile.Dedicated / profile.CloneNative / profile.Default). Construction scope only: the profile is part of what the Agent is, participates in session fingerprints, and cannot be swapped per call.

func WithServiceManager

func WithServiceManager(m ServiceManager) Option

WithServiceManager installs the backend that starts or locates the services declared with WithServices, and releases the run-scoped ones afterwards. Construction scope only.

func WithSkillMaterializer

func WithSkillMaterializer(m SkillMaterializer) Option

WithSkillMaterializer overrides how non-path skill sources are staged to disk. Construction scope only.

func WithSkillProvider

func WithSkillProvider(p SkillProvider) Option

WithSkillProvider installs the skill provider that resolves bare keys (and, when it implements a Catalogue method, feeds Inspect().Skills). Construction scope only: the provider is part of the Agent's identity, not a per-call knob.

func WithThreadStore

func WithThreadStore(store threadstore.Store) Option

WithThreadStore injects the thread storage backend that enables stateful conversations: with it, Agent.Thread persists and resumes driver checkpoints across runs and processes (memory.NewStore() for single-process hosts, a durable implementation for services). Without it Threads fail their runs with ErrThreadStoreRequired. Construction scope only; passing it to Run/Stream is a compile error (missing method ApplyRun).

func WithTools

func WithTools(definitions ...tool.Definition) Option

WithTools installs the immutable host-defined Tool set owned by this Agent. It is construction-scope only: Tools are a stable capability and authorization surface, so passing WithTools to Run or Stream is a compile error. Repeated WithTools options replace the whole set; WithTools() clears an earlier declaration.

Tool definitions and their schemas are validated before the Driver starts. The SDK exposes them to provider CLIs through a private, authenticated local runtime; applications do not need to configure MCP or manage another lifecycle object. Agent.Close closes that runtime.

func WithWorkspaceManager

func WithWorkspaceManager(m WorkspaceManager) Option

WithWorkspaceManager installs the backend that turns a WorkspaceSpec into a concrete working-directory lease (git worktrees, sandboxes, an external workspace service). Without one, specs resolve through the SDK's passthrough manager, which leases the base directory unchanged. Construction scope only: the manager is infrastructure the Agent is built on, not a per-call knob.

type Phase

type Phase string

Phase marks lifecycle boundaries on the streaming event types (TextDelta, Thinking, ToolCall). The zero value is the content-bearing middle of the lifecycle, so consumers that only care about content can ignore the field: start/end boundary events simply carry empty content.

const (
	// PhaseContent is the content-bearing default phase.
	PhaseContent Phase = ""
	// PhaseStart opens a message / reasoning / tool-call lifecycle.
	PhaseStart Phase = "start"
	// PhaseEnd closes a message / reasoning / tool-call lifecycle.
	PhaseEnd Phase = "end"
)

type Policy

type Policy struct {
	// Sandbox is the filesystem / process boundary strength.
	Sandbox SandboxLevel
	// WebSearch gates the provider's web-search capability.
	WebSearch FeatureLevel
	// Browser gates the provider's browser tooling.
	Browser FeatureLevel

	// Approvals routes and bounds human-in-the-loop requests: per-kind
	// modes (ask / auto-approve / auto-deny), the response Timeout, the
	// OnTimeout / OnReject fallbacks, and MaxRetries. Zero-valued fields
	// inherit the package defaults (Permission/PlanReview ask, Question
	// auto-deny, 30s timeout, abort on timeout/reject, 3 retries). See ApprovalPolicy
	// and the ApprovalsAutoDeny preset.
	Approvals ApprovalPolicy
}

Policy is the execution guardrail contract set via WithPolicy. Values are not CLI flag names: each driver maps them to provider-specific controls.

As an option value, Policy replaces as a whole ("nearer scope wins; everything but skills replaces"): a call-site WithPolicy substitutes the agent-default Policy entirely. Zero fields mean "inherit" at the driver boundary, so an all-zero Policy defers every dimension to the driver.

type PolicyCapabilityUnsupportedError

type PolicyCapabilityUnsupportedError = driver.PolicyCapabilityUnsupportedError

PolicyCapabilityUnsupportedError reports the rejected dimension, value, and Driver.

type ProcessInfo

type ProcessInfo struct {

	// Kind is ProcessSpawn, ProcessStdout, or ProcessStderr.
	Kind string
	// Text is the human-readable description (spawn).
	Text string
	// Bytes is the raw chunk (stdout/stderr); it may not align to lines.
	Bytes []byte
	// Metadata carries short string tags from the driver.
	Metadata map[string]string
	// Data carries structured driver-specific extensions.
	Data map[string]any
	// contains filtered or unexported fields
}

ProcessInfo carries process-level operational signals: child-process spawn details and raw stdout/stderr chunks. Most consumers ignore it; debugging and audit tooling reads it from the same stream instead of a second channel.

func (ProcessInfo) Meta

func (c ProcessInfo) Meta() EventMeta

type ProfileKind

type ProfileKind string

ProfileKind classifies where the effective provider profile lives.

const (
	// ProfileKindShared identifies a profile shared with the provider's normal
	// user configuration.
	ProfileKindShared ProfileKind = "shared"
	// ProfileKindHostManaged identifies a profile whose lifecycle is managed
	// by the embedding host.
	ProfileKindHostManaged ProfileKind = "host_managed"
)

type ProfileResourceKind

type ProfileResourceKind string

ProfileResourceKind names one provider-visible resource family.

const (
	// ProfileResourceSkills identifies skill resources.
	ProfileResourceSkills ProfileResourceKind = "skills"
	// ProfileResourceMCP identifies MCP server resources.
	ProfileResourceMCP ProfileResourceKind = "mcp"
	// ProfileResourceAgents identifies sub-agent declarations.
	ProfileResourceAgents ProfileResourceKind = "agents"
	// ProfileResourceHooks identifies hook declarations.
	ProfileResourceHooks ProfileResourceKind = "hooks"
	// ProfileResourceInstructions identifies instruction resources.
	ProfileResourceInstructions ProfileResourceKind = "instructions"
	// ProfileResourceConfig identifies provider configuration patches.
	ProfileResourceConfig ProfileResourceKind = "config"
)

type ProfileResourceMaterialization

type ProfileResourceMaterialization string

ProfileResourceMaterialization describes how a desired resource became provider-visible.

const (
	// ProfileResourceMaterializationNativeManaged means the provider manages
	// the resource natively.
	ProfileResourceMaterializationNativeManaged ProfileResourceMaterialization = "native_managed"
	// ProfileResourceMaterializationFileManaged means the package materialized
	// the resource as provider configuration files.
	ProfileResourceMaterializationFileManaged ProfileResourceMaterialization = "file_managed"
	// ProfileResourceMaterializationPromptInjected means the resource was
	// injected into the run instructions.
	ProfileResourceMaterializationPromptInjected ProfileResourceMaterialization = "prompt_injected"
	// ProfileResourceMaterializationFallback means a documented fallback was
	// used.
	ProfileResourceMaterializationFallback ProfileResourceMaterialization = "fallback"
	// ProfileResourceMaterializationNotMaterialized means the desired resource
	// was not made visible to the provider.
	ProfileResourceMaterializationNotMaterialized ProfileResourceMaterialization = "not_materialized"
)

type ProfileResourceSupport

type ProfileResourceSupport string

ProfileResourceSupport describes how portable a resource is for the bound driver.

const (
	// ProfileResourceSupportPortableCore is supported by every conforming
	// Driver through the portable core contract.
	ProfileResourceSupportPortableCore ProfileResourceSupport = "portable_core"
	// ProfileResourceSupportPortableExtended is supported through an optional
	// portable Driver extension.
	ProfileResourceSupportPortableExtended ProfileResourceSupport = "portable_extended"
	// ProfileResourceSupportNativeEscape requires provider-native handling.
	ProfileResourceSupportNativeEscape ProfileResourceSupport = "native_escape"
	// ProfileResourceSupportFallback uses a documented fallback representation.
	ProfileResourceSupportFallback ProfileResourceSupport = "fallback"
	// ProfileResourceSupportUnsupported means the Driver cannot represent the
	// resource.
	ProfileResourceSupportUnsupported ProfileResourceSupport = "unsupported"
)

type ProfileSnapshot

type ProfileSnapshot struct {
	// DriverType identifies the configured Driver.
	DriverType string
	// Profile is the Driver's observed native profile report.
	Profile AgentProfile
	// Kind classifies how the effective profile is managed.
	Kind ProfileKind
	// Fingerprint identifies the complete desired profile state.
	Fingerprint string
	// Resources reports desired and observed state by resource family.
	Resources []ResourceSnapshot
	// Warnings contains profile-wide non-fatal diagnostics.
	Warnings []string
}

ProfileSnapshot reports the desired versus observed profile resource state returned by Agent.ProfileState and Agent.SyncProfile.

type QuestionMode

type QuestionMode = driver.QuestionMode

QuestionMode routes the Question kind. Auto-approve is intentionally absent: a question has no legitimate synthesized answer.

const (
	// QuestionInherit falls back to the SDK default (auto-deny).
	QuestionInherit QuestionMode = driver.QuestionUnset
	// QuestionAsk routes the question to the host.
	QuestionAsk QuestionMode = driver.QuestionAsk
	// QuestionAutoDeny denies questions without asking.
	QuestionAutoDeny QuestionMode = driver.QuestionAutoReject
)

type QuotaReport

type QuotaReport = driver.QuotaReport

QuotaReport is the live quota/billing snapshot (Available=false when the driver cannot observe quota).

type RawStreams

type RawStreams = driver.RawStreams

RawStreams captures the complete raw stdout/stderr of one run.

type ResourceSnapshot

type ResourceSnapshot struct {
	// Kind identifies the resource family.
	Kind ProfileResourceKind
	// Fingerprint is the deterministic fingerprint of the desired resource.
	Fingerprint string
	// Managed lists resources controlled by this Agent's profile lifecycle.
	Managed []string
	// External lists provider-visible resources not controlled by this Agent.
	External []string
	// Support describes the Driver's portability level for the resource.
	Support ProfileResourceSupport
	// Materialization describes how the desired resource became visible to the
	// provider.
	Materialization ProfileResourceMaterialization
	// Warnings contains non-fatal observation or materialization diagnostics.
	Warnings []string
	// Error contains a resource-specific failure message, or is empty when the
	// resource has no reported failure.
	Error string
}

ResourceSnapshot is one resource row inside a ProfileSnapshot.

type Result

type Result struct {
	// RunID is the SDK-assigned execution identifier.
	RunID string
	// Model is the effective model reported by the driver.
	Model string
	// Provider is the upstream provider reported by the driver.
	Provider string
	// Text is the final assistant-facing text. It never contains raw
	// stdout/stderr dumps, Summary text, or provider terminal JSON.
	Text string
	// Summary is a short host-facing label suitable for lists and logs,
	// deliberately separate from Text.
	Summary string
	// Usage is normalized token/cost accounting. nil means the provider did
	// not report usage; a non-nil zero value means usage was observed and all
	// normalized metrics were explicitly zero.
	Usage *Usage
	// Metadata is Driver-reported result metadata.
	Metadata map[string]string
	// contains filtered or unexported fields
}

Result is the outcome of one successful run. High-frequency fields are flat; audit surfaces are gathered behind Raw() / Transcript() / Services(); structured output decodes via Decode.

A run that completed but failed at the business level does not return a Result directly — it returns a *RunError whose Result field carries this same value (see RunError).

func RunAs

func RunAs[T any](ctx context.Context, r Runner, prompt string, opts ...CallOption) (T, *Result, error)

RunAs runs one prompt and decodes the structured output into T. It accepts any Runner, so stateless Agents and stateful Threads work interchangeably:

triage, res, err := adaptor.RunAs[Triage](ctx, agent, prompt)

RunAs prepends WithSchema[T]() to the call options; explicit options (including another WithSchema) apply after it and win. On a run error the zero T is returned together with Run's (*Result, error) contract; on success a decode failure surfaces as the returned error with the Result still available.

func (*Result) Decode

func (r *Result) Decode(v any) error

Decode unmarshals the run's structured output into v.

When the run requested structured output (WithSchema[T] / RunAs[T]), the validated payload is the only source: invalid output (possible under SchemaReturnInvalid — the default policy fails the run instead) and empty RawJSON are errors. Runs without a schema fall back to interpreting Text as a JSON document — the schema-less convenience decode.

func (*Result) Raw

func (r *Result) Raw() RawStreams

Raw returns the complete raw stdout/stderr and exact provider terminal JSON captured during the run — the stable audit/replay surface. It is deliberately separate from Text and Transcript (the layers never contaminate each other). The returned Terminal and JSON bytes are deep copies.

func (*Result) Services

func (r *Result) Services() []ServiceReport

Services returns the runtime-service execution reports for this run. Reports observed by the driver are merged by stable service ID with reports from services the SDK actually ensured; driver fields override matching SDK fields and missing fields are filled from the SDK observation. The returned values, including Metadata maps, are copies.

The report deliberately does not echo the typed ServiceRef.MCP declaration. Three reasons, in order of weight:

  1. Direction. ServiceRef.MCP is pre-run *input* the host itself authored (via WithServices or the provider it installed); ServiceReport is post-run *observation*. Echoing an input back as an observation invites hosts to read a declaration as evidence the server was actually reached, which no driver reports today.
  2. Fill honesty. Reports come from the driver (Response.RuntimeServices). A driver echoing a report cannot know the SDK-side MCP declaration, so the field would be populated on the SDK fallback path and empty on the driver path — the exact "sometimes true" shape the SDK avoids.
  3. Secrecy. The ref→report projection already drops SecretEnv on purpose. MCP carries the endpoint URL and BearerTokenEnvVar next to it; putting that pair into the surface hosts log wholesale works against the same rule.

Hosts that need the declaration have it: it is the value they passed in.

func (*Result) Transcript

func (r *Result) Transcript() []TranscriptItem

Transcript returns the normalized semantic item stream parsed by the driver. The returned slice is a copy.

type Role

type Role = driver.Role

Role identifies the speaker of a text event. It aliases the driver SPI type; the zero value is RoleAssistant.

const (
	// RoleAssistant is the default speaker for text events.
	RoleAssistant Role = driver.RoleAssistant
	// RoleUser marks a text lifecycle synthesized above the driver layer
	// (bridges replaying the human turn). Drivers never emit it.
	RoleUser Role = driver.RoleUser
)

type RunAttachment

type RunAttachment struct {
	// Services are the concrete endpoints this provider ensured for the run.
	Services []ServiceRef
	// Events optionally streams provider-side events into the run.
	Events RunEventSource
}

RunAttachment is what one provider contributes to one run.

Services are merged into the run's runtime payload and — for every ref carrying a typed MCP field — appended to the driver's MCP server set. The host's own WithMCP declaration is preserved: attachment servers are added alongside it, never in place of it. A ref's URL, MCP.BearerTokenEnvVar, and SecretEnv together are how a per-run endpoint publishes an authenticated MCP server without the token ever entering a public report: SecretEnv reaches the driver process environment only.

Events, when non-nil, is folded straight into the run's single event channel, interleaved with the driver's own events — there is no second stream to merge and no wrapper goroutine on the driver's hot path.

type RunError

type RunError struct {
	// Reason classifies the failure.
	Reason FailureReason
	// Message is the human-readable failure message from the driver/SDK.
	Message string
	// Details carries driver-specific structured failure metadata.
	Details map[string]any
	// Result is the full result of the completed-but-failed run. It is
	// always non-nil when the SDK returns a *RunError.
	Result *Result
}

RunError is the typed error for a run that completed but failed at the business level (approval denied / timed out, policy violation, agent error). It follows the *exec.ExitError convention: the error carries the full execution Result, so partial output, usage, and the transcript stay accessible on the failure path.

func (*RunError) Error

func (e *RunError) Error() string

Error implements the error interface.

func (*RunError) Unwrap

func (e *RunError) Unwrap() error

Unwrap returns the sentinel matching Reason so that errors.Is(err, adaptor.ErrApprovalDenied) and friends hold.

type RunEventSource

type RunEventSource func(ctx context.Context, runID string) <-chan Event

RunEventSource subscribes to one run's provider-side events, already projected onto the SDK event vocabulary (delegation providers emit SubagentUpdate).

Contract: the returned channel must be closed once ctx is done, and every event already published for the run must be delivered before that close. The SDK drains the channel to closure before it closes the run's event channel, so a source that abandons its tail on cancellation clips terminal events — flush first, then close. RunStarted and RunFinished are reserved for the core-owned merged-run envelope and are filtered if a source supplies them. A nil channel is treated as "no events".

type RunFinished

type RunFinished struct {

	// RunID is the run identifier reported by the Driver event.
	RunID string
	// ThreadID is the provider conversation identifier, when reported.
	ThreadID string
	// Usage is the token accounting reported on normal completion.
	Usage *Usage
	// Failed reports that this is a run.error terminal marker.
	Failed bool
	// Reason classifies the failure (Failed == true).
	Reason FailureReason
	// Message is the driver's failure message (Failed == true).
	Message string
	// contains filtered or unexported fields
}

RunFinished marks the end of a streamed run. Translated from run.finished (Failed == false, Usage populated when the driver reports it) and run.error (Failed == true with the classified Reason / Message).

RunFinished is informational: the authoritative outcome — including the full Result and the typed *RunError — always comes from Stream.Result().

func (RunFinished) Meta

func (c RunFinished) Meta() EventMeta

type RunServiceProvider

type RunServiceProvider interface {
	// AttachRun binds the provider's service to one run.
	AttachRun(ctx context.Context, runID string) (RunAttachment, error)
	// DetachRun releases everything AttachRun bound to the run.
	DetachRun(ctx context.Context, runID string) error
}

RunServiceProvider is the extension point ecosystem packages implement to bind a live, run-scoped service to every invocation of an Agent. It is the mechanism behind delegation.Service.Option(): the root package never learns the word "team" — it only knows that something asked to be attached to this run, and that whatever it returns must reach the driver and the event stream.

Lifecycle, per run:

AttachRun(ctx, runID)  — after workspace and declared runtime services are
                         resolved, but before request/MCP resolution and
                         Driver dispatch. Returning an error is a pre-launch
                         failure: the Driver never starts, the error surfaces
                         through Result(), and every provider already attached
                         for this run is detached again.
  ... the run ...
DetachRun(ctx, runID)  — after provider events have flushed, but before the
                         run's terminal event and channel close. The SDK uses
                         a cancellation-detached, bounded context so teardown
                         is attempted after cancellation without allowing a
                         broken hook to wedge Result. Errors are joined into
                         the observable run outcome.

Implementations must be safe for concurrent runs of the same Agent: AttachRun and DetachRun are keyed by run ID and may overlap.

type RunSettings

type RunSettings struct {
	// contains filtered or unexported fields
}

RunSettings collects every setting that can be overridden at the call site. Fields are unexported; ecosystem packages write through the exported methods below, whose semantics encode the merge rule (Set* replaces, Add* appends). The root package's own options go through the same methods so the extension surface stays self-validating.

func (*RunSettings) AddRunServiceProvider

func (s *RunSettings) AddRunServiceProvider(p RunServiceProvider)

AddRunServiceProvider appends a run-scoped service provider — the controlled extension surface behind ecosystem options such as delegation.Service.Option(). Providers append rather than replace, and a provider already present is not added twice: the same option value used in both New and Run attaches exactly once, which is what keeps its MCP server key unique (a duplicate would fail the run before launch).

func (*RunSettings) AddSkills

func (s *RunSettings) AddSkills(refs ...skill.Ref)

AddSkills appends skill references for the target scope — the single append-merged option family: call-site refs never displace the agent defaults, they extend them.

func (*RunSettings) SetAgents

func (s *RunSettings) SetAgents(specs []driver.AgentSpec)

SetAgents replaces the sub-agent spec set and declares the resource. An empty slice declares "explicitly no sub-agents".

func (*RunSettings) SetApprovalHandler

func (s *RunSettings) SetApprovalHandler(h ApprovalHandler)

SetApprovalHandler replaces the approval callback (form A of approval consumption). A nil handler restores event-form consumption.

func (*RunSettings) SetConfigPatches

func (s *RunSettings) SetConfigPatches(patches []driver.ProfileConfigPatch)

SetConfigPatches replaces the profile config patch set and declares the resource. An empty slice declares "explicitly no patches".

func (*RunSettings) SetHooks

func (s *RunSettings) SetHooks(specs []driver.HookSpec)

SetHooks replaces the hook spec set and declares the resource. An empty slice declares "explicitly no hooks".

func (*RunSettings) SetIdentity

func (s *RunSettings) SetIdentity(id Identity)

SetIdentity replaces the caller identity propagated to host hooks and the driver.

func (*RunSettings) SetInstructions

func (s *RunSettings) SetInstructions(text string)

SetInstructions replaces the extra instruction text handed to the driver and declares the instructions resource as host-managed. Empty text clears the effective instructions (an explicit clear still declares).

func (*RunSettings) SetInstructionsBundle

func (s *RunSettings) SetInstructionsBundle(ref *driver.InstructionsBundleRef)

SetInstructionsBundle replaces the full instruction bundle (path- or content-based) and declares the instructions resource. A nil ref clears the effective bundle while still declaring the resource.

func (*RunSettings) SetMCPServers

func (s *RunSettings) SetMCPServers(servers []mcp.Server)

SetMCPServers replaces the MCP server set as a whole value. An empty (or nil) slice is an explicit clear: it substitutes the agent default with "no servers" rather than inheriting it.

func (*RunSettings) SetMetadata

func (s *RunSettings) SetMetadata(k, v string)

SetMetadata sets one audit metadata key. Keys merge per key: a call-site value overrides the same key from the agent defaults and leaves the other default keys intact.

func (*RunSettings) SetModel

func (s *RunSettings) SetModel(m string)

SetModel replaces the effective model for the target scope. Empty and whitespace-only values mean no override, matching the Driver Request contract and preventing an all-space model name from reaching providers.

func (*RunSettings) SetOutputSchema

func (s *RunSettings) SetOutputSchema(schema driver.OutputSchema)

SetOutputSchema replaces the structured output request for this run.

func (*RunSettings) SetOutputSchemaError

func (s *RunSettings) SetOutputSchemaError(err error)

SetOutputSchemaError records a schema construction failure. The run fails with this error before the driver launches — schema bugs are programmer errors that must not silently degrade into unvalidated output. The error is sticky: a valid schema set later in the option list does not clear it.

func (*RunSettings) SetPolicy

func (s *RunSettings) SetPolicy(p Policy)

SetPolicy replaces the whole execution policy ("everything else replaces": a call-site policy substitutes the agent-default policy as one value, it does not merge field-wise).

func (*RunSettings) SetServices

func (s *RunSettings) SetServices(specs []ServiceSpec)

SetServices replaces the declared runtime-service set as a whole value. An empty (or nil) slice is an explicit clear: it substitutes the agent default with "no services" rather than inheriting it.

func (*RunSettings) SetSpawn

func (s *RunSettings) SetSpawn()

SetSpawn forces a fresh provider process for the target scope.

func (*RunSettings) SetTimeout

func (s *RunSettings) SetTimeout(d time.Duration)

SetTimeout replaces the wall-clock budget for one run. Zero means no SDK-imposed deadline.

func (*RunSettings) SetWorkspace

func (s *RunSettings) SetWorkspace(dir string)

SetWorkspace replaces the working directory for the target scope.

func (*RunSettings) SetWorkspaceSpec

func (s *RunSettings) SetWorkspaceSpec(spec WorkspaceSpec)

SetWorkspaceSpec replaces the workspace provisioning strategy. A non-nil spec routes the run through the WorkspaceManager (the passthrough manager when none is installed) instead of the direct lease synthesis.

type RunStarted

type RunStarted struct {

	// RunID is the run identifier reported by the Driver event.
	RunID string
	// ThreadID is the provider conversation identifier, when reported.
	ThreadID string
	// contains filtered or unexported fields
}

RunStarted marks the beginning of a streamed run (StreamKind run.started).

func (RunStarted) Meta

func (c RunStarted) Meta() EventMeta

type Runner

type Runner interface {
	// Run executes one prompt to completion through the unified event pipeline.
	Run(ctx context.Context, prompt string, opts ...CallOption) (*Result, error)
	// Stream starts one prompt and returns its live typed event stream.
	Stream(ctx context.Context, prompt string, opts ...CallOption) Stream
}

Runner is the single execution contract shared by Agent (stateless runs) and Thread (stateful conversations). Bridges, RunAs[T], and host decorators accept a Runner so both are interchangeable.

type SandboxLevel

type SandboxLevel = driver.IsolationLevel

SandboxLevel controls filesystem and process boundary strength. It aliases the driver SPI type so policies flow to Drivers without conversion.

const (
	// SandboxInherit leaves the sandbox to the agent default or the
	// driver's own fallback.
	SandboxInherit SandboxLevel = driver.IsolationInherit
	// ReadOnly requests a read-only workspace.
	ReadOnly SandboxLevel = driver.IsolationReadOnly
	// WorkspaceWrite allows writes inside the resolved workspace.
	WorkspaceWrite SandboxLevel = driver.IsolationWorkspaceWrite
	// Unrestricted maps to each agent's "full access" / danger sandbox
	// (or the closest available behavior).
	Unrestricted SandboxLevel = driver.IsolationUnrestricted
)

type SchemaOption

type SchemaOption func(*schemaSettings)

SchemaOption customizes WithSchema[T]: how the JSON Schema document is generated from the Go type, and how the structured-output request is shaped (name, description, invalid policy).

func SchemaAllowAdditionalProperties

func SchemaAllowAdditionalProperties() SchemaOption

SchemaAllowAdditionalProperties relaxes the default strict-object behavior of generated schemas.

func SchemaDescription

func SchemaDescription(desc string) SchemaOption

SchemaDescription sets a provider-facing schema description when supported.

func SchemaInlineReferences

func SchemaInlineReferences() SchemaOption

SchemaInlineReferences asks the generator to inline referenced definitions. Useful for CLIs whose accepted schema subset rejects $defs/$ref. Inlining a recursive Go type is an error.

func SchemaName

func SchemaName(name string) SchemaOption

SchemaName sets a provider-facing schema name when supported.

func SchemaRequireExplicitTags

func SchemaRequireExplicitTags() SchemaOption

SchemaRequireExplicitTags makes only fields tagged jsonschema:"required" required in the generated schema.

func SchemaReturnInvalid

func SchemaReturnInvalid() SchemaOption

SchemaReturnInvalid returns invalid structured output as StructuredOutput.Valid=false (readable via Result.Decode's error) instead of failing the run.

func SchemaUseGoComments

func SchemaUseGoComments(base, path string) SchemaOption

SchemaUseGoComments adds Go comments from path under base as schema descriptions when the generator can resolve them.

type ServiceManager

type ServiceManager interface {
	// Ensure starts or locates the desired services and returns the endpoints
	// actually made available to the run.
	Ensure(ctx context.Context, req ServiceRequest) ([]ServiceRef, error)
	// ReleaseByRun releases run-scoped services owned by runID.
	ReleaseByRun(ctx context.Context, runID string) error
	// ReleaseByLabels releases services selected by host-defined labels.
	ReleaseByLabels(ctx context.Context, labels map[string]string) error
}

ServiceManager is the host hook that starts or locates runtime services. Install it with WithServiceManager. Implementations must be safe for concurrent runs of one Agent.

type ServiceRef

type ServiceRef = driver.RuntimeServiceRef

ServiceRef is a concrete runtime service endpoint. Its MCP field is the typed way a service publishes an MCP server into the run, and its SecretEnv field is the subprocess-only channel for run-scoped secrets (bearer tokens) that never reach public reports.

type ServiceReport

type ServiceReport = driver.RuntimeServiceReport

ServiceReport is the execution report for one ensured runtime service.

type ServiceRequest

type ServiceRequest struct {
	// RunID is the package-assigned execution identifier.
	RunID string
	// DriverType identifies the configured Driver.
	DriverType string
	// Agent is the effective host-supplied identity for the run.
	Agent Identity
	// Config is optional opaque Driver configuration. It is nil when the
	// configured Driver retains its construction-time configuration internally.
	Config any
	// Workspace is the resolved workspace lease, if one was acquired.
	Workspace WorkspaceLease
	// Desired is the complete service declaration for the run.
	Desired []ServiceSpec
	// Metadata is the effective audit metadata for the run.
	Metadata map[string]string
}

ServiceRequest is the immutable run envelope passed to ServiceManager.Ensure. Slice and map fields are owned by the SDK for the duration of the call; managers must copy values they retain afterwards.

type ServiceSpec

type ServiceSpec = driver.RuntimeServiceSpec

ServiceSpec declares one runtime service a run needs — an already-known endpoint (URL) or a command/port a ServiceManager starts before the driver launches.

type SharedOption

type SharedOption interface {
	Option
	CallOption
}

SharedOption is the return type of dual-scope options: used in New it is the Agent's default, used in Run/Stream it overrides this call only. Most options that configure execution values return it.

func OnApproval

func OnApproval(h ApprovalHandler) SharedOption

OnApproval installs the approval callback — form A of approval consumption. Every human-in-the-loop request whose policy mode is "ask" invokes the handler with a live *ApprovalRequest; the handler resolves it (Approve / Deny / Answer) and returns nil, or returns an error to abort the run. When no handler is installed the request arrives as a *ApprovalRequest event on the Stream instead (form B); either way an unconsumed request times out into the Policy.Approvals fallback.

In New the handler is the agent default; in Run/Stream it overrides this invocation only ("nearer scope wins").

func WithIdentity

func WithIdentity(id Identity) SharedOption

WithIdentity sets the caller identity (tenant / user / profile / agent scoping) propagated to host hooks and the driver. See Identity.

func WithInstructions

func WithInstructions(text string) SharedOption

WithInstructions supplies extra instruction text alongside the prompt. Nearer scope replaces: a call-site value substitutes the agent default.

func WithMCP

func WithMCP(servers ...mcp.Server) SharedOption

WithMCP replaces the MCP server set as a whole value ("everything else replaces"): in New it is the agent default, in Run/Stream it substitutes the default for this invocation only. Calling WithMCP() with no servers is an explicit clear — the run sees no MCP servers even when the agent default has some. Server specs are validated against the driver's declared MCP capability before the driver launches; unsupported transports fail the run with ErrMCPTransportUnsupported and the driver is never started.

func WithMetadata

func WithMetadata(k, v string) SharedOption

WithMetadata attaches one audit metadata key/value to runs. Metadata merges per key: call-site keys override same-named default keys and leave the rest of the defaults intact.

func WithModel

func WithModel(m string) SharedOption

WithModel selects the model. In New it is the Agent's default model; in Run/Stream it overrides this invocation only (delivered to the driver as the per-run model override).

func WithPolicy

func WithPolicy(p Policy) SharedOption

WithPolicy sets the execution policy: sandbox, optional feature levels, and approvals. The policy replaces as a whole value; it does not merge field-wise with the agent default.

func WithProfileResources

func WithProfileResources(res profile.Resources) SharedOption

WithProfileResources declares the desired profile-shaped resource set in one value. Each resource keeps its own merge rule (the same rules as the dedicated options):

  • Skills append (like WithSkills);
  • MCP replaces when non-nil (like WithMCP);
  • Agents / Hooks / Config replace and declare when the field is non-nil — an explicitly empty slice declares "none";
  • Instructions replace and declare when non-nil.

In New the resources are agent defaults; in Run/Stream they override this invocation only. Every declared resource lands in the run's ProfilePayload, and ProfileState reports truthfully whether the Driver actually materialized it.

func WithRunServices

func WithRunServices(providers ...RunServiceProvider) SharedOption

WithRunServices attaches run-scoped service providers to every invocation: the generic form of what ecosystem packages ship as their own one-liner option (delegation.Service.Option()). Each provider is attached after the run ID is minted and before the driver is dispatched, contributes its endpoints to the run's runtime/MCP payload, may stream its own events into the run's event channel, and is detached once the run's events are done.

Providers append rather than replace, and the same provider is never attached twice — passing one option value in both New and Run is safe.

func WithServices

func WithServices(specs ...ServiceSpec) SharedOption

WithServices declares the runtime services a run needs — dev servers, databases, tool sidecars. They are ensured through the installed ServiceManager before the driver launches, and the resulting endpoints reach the driver in the run's runtime payload; a service that publishes a typed ServiceRef.MCP additionally joins the run's MCP server set alongside (never in place of) WithMCP.

The declaration replaces as a whole value: calling WithServices() with no specs is an explicit clear. Without a ServiceManager the declaration is inert — the SDK never invents endpoints for services nobody manages.

func WithSkills

func WithSkills(refs ...SkillRef) SharedOption

WithSkills appends skill references. This is the single append-merged option family: in New the refs are the agent's default skills, in Run/Stream they extend (never displace) the defaults for this invocation only. Bare keys (skill.Key) are resolved through the SkillProvider; inline values (skill.Dir / skill.FS / skill.Inline) are taken at face value. Duplicate keys must be structurally equal — conflicting duplicates fail the run with ErrSkillKeyConflict.

func WithSpawn

func WithSpawn() SharedOption

WithSpawn forces a fresh provider process instead of reusing the driver's default persistent process. In New it applies to every invocation; in Run/Stream it overrides this invocation only. Stateless Agent runs and drivers without persistent-process support already spawn regardless.

func WithTimeout

func WithTimeout(d time.Duration) SharedOption

WithTimeout bounds one run's wall-clock time. In New it is the default budget for every run; in Run/Stream it overrides this invocation only. The SDK enforces it via context deadline; a run that exceeds it fails with context.DeadlineExceeded.

func WithWorkspace

func WithWorkspace(dir string) SharedOption

WithWorkspace sets the working directory the agent operates in.

func WithWorkspaceSpec

func WithWorkspaceSpec(spec WorkspaceSpec) SharedOption

WithWorkspaceSpec selects how the run's workspace is provisioned — adaptor.SharedWorkspace{} to reuse the project directory, adaptor.GitWorktreeWorkspace{...} for an isolated worktree, adaptor.DriverManagedWorkspace{} to let the Driver choose. It replaces as a whole value: in New it is the agent default, in Run/Stream it overrides this invocation only.

WithWorkspace(dir) and WithWorkspaceSpec compose: the directory is the base CWD handed to the WorkspaceManager, the spec is the strategy. Setting either a spec or a manager routes the run through managed lease resolution; setting neither keeps the plain "run here" behavior.

type SharedWorkspace

type SharedWorkspace struct{}

SharedWorkspace requests direct reuse of the project workspace.

type SkillKeyConflictError

type SkillKeyConflictError = skill.SkillKeyConflictError

SkillKeyConflictError reports conflicting duplicate skill keys.

type SkillMaterializationError

type SkillMaterializationError = skill.SkillMaterializationError

SkillMaterializationError reports a failed skill staging.

type SkillMaterializer

type SkillMaterializer = skill.Materializer

SkillMaterializer converts non-path skill sources into on-disk skill directories before the driver launches.

type SkillProvider

type SkillProvider = skill.Provider

SkillProvider resolves bare skill keys to full skill descriptions. Implementations that also implement skill.Catalog (a Catalogue method) additionally power Inspect().Skills enumeration.

type SkillRef

type SkillRef = skill.Ref

SkillRef references a skill for WithSkills: either a bare key resolved through the SkillProvider (skill.Key) or a fully described inline skill (skill.Dir / skill.FS / skill.Inline / skill.Require). Alias of the driver SPI type — skill package constructors produce values of exactly this type.

type SkillSnapshot

type SkillSnapshot = driver.SkillSnapshot

SkillSnapshot reports the resolved skill set and its sync state.

type Stream

type Stream interface {
	// Events returns the unified typed event channel. It is closed when
	// the run ends (after the final events, including the terminal
	// Dropped marker when events were dropped, have been delivered).
	Events() <-chan Event
	// Result blocks until the run ends and returns the final outcome —
	// exactly Run's contract: (*Result, nil) on success, (nil, *RunError)
	// on business failure, (nil, error) on infrastructure failure.
	// Result may be called multiple times and from any goroutine.
	Result() (*Result, error)
	// RunID returns the SDK-assigned execution identifier, available
	// immediately (before the first event).
	RunID() string
	// Cancel aborts the run and immediately releases blocked event publishers
	// and approval waiters. It is idempotent. Buffered Events may still be
	// drained before reading Result().
	Cancel()
}

Stream is the small interface representing one running invocation. One event channel carries everything — text/thinking deltas, tool calls, process output, notices, approval requests — and Result() is the single close-out.

Consumption contract:

stream := agent.Stream(ctx, prompt)
for ev := range stream.Events() {
    switch e := ev.(type) {
    case adaptor.TextDelta:        // render e.Text
    case adaptor.ToolCall:         // show e.Name
    case *adaptor.ApprovalRequest: // e.Approve / e.Deny / e.Answer
    }
}
res, err := stream.Result()

Events() closes after run-scoped resources have been released; Result() then returns immediately with the same Result / *RunError / infrastructure-error contract as Run. Consumers must continuously drain Events. The default backpressure mode may discard only high-frequency deltas; approvals, lifecycle, terminal, transcript and drop-report events remain reliable and can therefore apply backpressure. A consumer which abandons the loop must call Cancel first.

type StructuredOutputUnsupportedError

type StructuredOutputUnsupportedError = driver.StructuredOutputUnsupportedError

StructuredOutputUnsupportedError reports a capability-matrix miss.

type SubagentEventKind

type SubagentEventKind string

SubagentEventKind classifies a SubagentUpdate.

const (
	// SubagentStarted marks a delegated subagent beginning work.
	SubagentStarted SubagentEventKind = "started"
	// SubagentDelta carries incremental subagent output.
	SubagentDelta SubagentEventKind = "delta"
	// SubagentFinished marks a delegated subagent completing.
	SubagentFinished SubagentEventKind = "finished"
)

type SubagentUpdate

type SubagentUpdate struct {

	// Agent is the delegation key of the subagent.
	Agent string
	// Kind classifies the update.
	Kind SubagentEventKind
	// Delta is the incremental output chunk (SubagentDelta).
	Delta string
	// Data carries structured details.
	Data map[string]any
	// contains filtered or unexported fields
}

SubagentUpdate reports remote progress of a delegated subagent on the parent Agent's own event stream. Optional delegation host components can publish it through a RunServiceProvider attachment.

func (SubagentUpdate) Meta

func (c SubagentUpdate) Meta() EventMeta

type TerminalPayload

type TerminalPayload = driver.TerminalPayload

TerminalPayload preserves the exact provider terminal JSON recognized by the driver parser and its provider-native event name.

type TextDelta

type TextDelta struct {

	// MessageID groups the deltas of one message lifecycle.
	MessageID string
	// Text is the incremental content chunk (empty on start/end phases).
	Text string
	// Role is the speaker; zero value RoleAssistant.
	Role Role
	// Phase discriminates lifecycle boundary events from content.
	Phase Phase
	// contains filtered or unexported fields
}

TextDelta is one assistant (or bridge-synthesized user) text event. Translated from StreamKinds text.start / text.content / text.end, discriminated by Phase; only PhaseContent events carry Text.

func (TextDelta) Meta

func (c TextDelta) Meta() EventMeta

type Thinking

type Thinking struct {

	// MessageID groups the deltas of one reasoning lifecycle.
	MessageID string
	// Text is the incremental reasoning chunk (empty on start/end phases).
	Text string
	// Phase discriminates lifecycle boundary events from content.
	Phase Phase
	// contains filtered or unexported fields
}

Thinking is one reasoning/thinking text event. Translated from reasoning.start / reasoning.content / reasoning.end, discriminated by Phase; only PhaseContent events carry Text.

func (Thinking) Meta

func (c Thinking) Meta() EventMeta

type Thread

type Thread struct {
	// contains filtered or unexported fields
}

Thread is a stateful conversation handle: the same Runner contract as Agent, plus continuity — every run resumes the driver checkpoint stored under the thread key and persists the new checkpoint afterwards.

The thread key is the host-owned, opaque conversation identity. The internal session ID and the Driver's native resume handle remain storage details, reachable only through Checkpoint for audit.

agent.Thread("tenant-1/issue-123")            // continue_or_start
agent.Thread("k", adaptor.ResumeOnly())       // continue_only
th.Fork("tenant-1/issue-123/alt")             // fork (first run)

A Thread handle is cheap: it holds no open resources, and any number of handles for the same key are interchangeable (state lives in the threadstore.Store). Concurrent runs on the same key are serialized by the store lease — the loser fails fast with ErrThreadBusy. The configured Driver must declare Sessions.SupportsResume and implement both driver.SessionCodecProvider and driver.SessionConfigFingerprinter; Run/Stream reject an incomplete contract before acquiring resources or touching the store.

func (*Thread) Checkpoint

func (t *Thread) Checkpoint(ctx context.Context) (*Checkpoint, error)

Checkpoint returns the driver resume handle currently stored under the thread key, normalized through the driver's session codec (audit / debugging use — the SDK resumes threads by itself). It fails with ErrThreadNotFound when the key has no active conversation and with ErrThreadStoreRequired when the agent has no store. Corrupt or unusable durable state returns ErrThreadCheckpointMissing or ErrThreadIncompatible; Checkpoint never returns an invalid checkpoint with a nil error.

func (*Thread) Fork

func (t *Thread) Fork(newKey string) *Thread

Fork branches the conversation to newKey — the "regenerate from here / try another direction" button. The first run on the returned Thread forks from t's current conversation (the parent stays intact and active under its own key); afterwards the fork continues independently under newKey.

The parent conversation is resolved when the fork's first run executes; if the parent thread has no stored conversation by then, the run fails with ErrThreadNotFound. Fork panics on an empty newKey.

func (*Thread) Key

func (t *Thread) Key() string

Key returns the thread key the handle is bound to.

func (*Thread) Run

func (t *Thread) Run(ctx context.Context, prompt string, opts ...CallOption) (*Result, error)

Run executes one prompt on the thread to completion: resume the stored conversation per the thread's mode, run the driver, persist the new checkpoint. It has the same drain-the-stream and error contracts as Agent.Run, plus the thread error vocabulary (ErrThreadBusy, ErrThreadNotFound, ErrThreadIncompatible, ...).

func (*Thread) Stream

func (t *Thread) Stream(ctx context.Context, prompt string, opts ...CallOption) Stream

Stream starts one prompt on the thread and returns the live Stream immediately — the same consumption contract as Agent.Stream carrying the session context per turn. Startup and session-coordination failures surface through the normal contract (closed Events channel + Result() error), never as a second return value.

type ThreadOption

type ThreadOption interface {
	// contains filtered or unexported methods
}

ThreadOption tweaks how a Thread binds to its key. ResumeOnly is the sole Thread option.

func ResumeOnly

func ResumeOnly() ThreadOption

ResumeOnly makes the Thread resume-only: runs fail with ErrThreadNotFound when no conversation exists under the key (instead of silently starting a fresh one) and with ErrThreadIncompatible when the stored conversation no longer matches the current configuration. Use it when starting over would be a bug — e.g. replying inside an existing support ticket.

type ToolCall

type ToolCall struct {

	// ID is the tool-call correlation identifier.
	ID string
	// Name is the tool name (PhaseStart).
	Name string
	// Args is the complete initial argument snapshot (PhaseStart, optional).
	Args map[string]any
	// ArgsDelta is one streamed argument fragment (PhaseContent).
	ArgsDelta string
	// Result is the optional result attached to the end marker (PhaseEnd).
	Result map[string]any
	// Phase discriminates start / argument-streaming / end.
	Phase Phase
	// contains filtered or unexported fields
}

ToolCall is one tool-call lifecycle event. Translated from tool_call.start / tool_call.args / tool_call.end, discriminated by Phase:

  • PhaseStart: Name (and Args, when the driver sends a complete initial snapshot) identify the invocation — the natural "render the tool card" event.
  • PhaseContent: ArgsDelta carries one streamed argument fragment (usually a JSON fragment) for drivers with argument streaming.
  • PhaseEnd: closes the lifecycle; Result is populated when the driver attaches it to the end marker.

func (ToolCall) Meta

func (c ToolCall) Meta() EventMeta

type ToolResult

type ToolResult struct {

	// ID correlates with the originating ToolCall.ID.
	ID string
	// Result is the structured tool result.
	Result map[string]any
	// contains filtered or unexported fields
}

ToolResult carries a completed tool result (StreamKind tool_call.result).

func (ToolResult) Meta

func (c ToolResult) Meta() EventMeta

type TranscriptItem

type TranscriptItem = driver.TranscriptItem

TranscriptItem is the normalized semantic transcript unit.

type Usage

type Usage = driver.Usage

Usage is normalized token/cost accounting. Individual observed values may be zero; Result.Usage is nil when the provider reported no usage.

type WorkspaceLease

type WorkspaceLease = driver.WorkspaceLease

WorkspaceLease is the concrete working directory a manager returns.

type WorkspaceManager

type WorkspaceManager interface {
	// Resolve provisions or selects a workspace and returns its concrete lease.
	Resolve(ctx context.Context, req WorkspaceRequest) (WorkspaceLease, error)
	// Release applies mode to a previously resolved lease.
	Release(ctx context.Context, lease WorkspaceLease, mode WorkspaceReleaseMode) error
}

WorkspaceManager is the host hook that turns a WorkspaceSpec into a concrete lease. Install it with WithWorkspaceManager. Implementations must be safe for concurrent runs of one Agent.

type WorkspaceReleaseMode

type WorkspaceReleaseMode string

WorkspaceReleaseMode tells a WorkspaceManager what to do after a run.

const (
	// WorkspaceReleaseKeep leaves the workspace available after the run.
	WorkspaceReleaseKeep WorkspaceReleaseMode = "keep"
	// WorkspaceReleaseStop asks the manager to tear down run-scoped state.
	WorkspaceReleaseStop WorkspaceReleaseMode = "stop"
)

type WorkspaceRequest

type WorkspaceRequest struct {
	// BaseCWD is the effective working directory before managed provisioning.
	BaseCWD string
	// Spec describes the requested provisioning strategy.
	Spec WorkspaceSpec
	// Metadata is the effective audit metadata for the run.
	Metadata map[string]string
}

WorkspaceRequest is passed to WorkspaceManager.Resolve after agent defaults and per-call workspace options have been merged.

type WorkspaceSpec

type WorkspaceSpec interface {
	// contains filtered or unexported methods
}

WorkspaceSpec is the closed set of workspace provisioning requests: SharedWorkspace, GitWorktreeWorkspace, and DriverManagedWorkspace.

Directories

Path Synopsis
Package adaptertest is the conformance suite for the driver SPI.
Package adaptertest is the conformance suite for the driver SPI.
bridges
a2a
Package a2a exposes an adaptor Runner as an A2A-compatible agent.
Package a2a exposes an adaptor Runner as an A2A-compatible agent.
agui
Package agui translates adaptor requests, events, and approvals to and from the AG-UI protocol.
Package agui translates adaptor requests, events, and approvals to and from the AG-UI protocol.
internal/bridgekey
Package bridgekey provides the collision-free encoding used when an external protocol identifier must be namespaced before it becomes an adaptor Thread key.
Package bridgekey provides the collision-free encoding used when an external protocol identifier must be namespaced before it becomes an adaptor Thread key.
sse
Package sse exposes HTTP Server-Sent Events handlers for the adaptor v1 Runner/Event/Result contracts.
Package sse exposes HTTP Server-Sent Events handlers for the adaptor v1 Runner/Event/Result contracts.
subagentstream
Package subagentstream merges host delegation events into a Runner's single adaptor Event stream as SubagentUpdate values.
Package subagentstream merges host delegation events into a Runner's single adaptor Event stream as SubagentUpdate values.
Package claude provides the built-in Driver implementation for the Claude Code CLI.
Package claude provides the built-in Driver implementation for the Claude Code CLI.
clients
a2a
Package a2a provides thin, host-oriented client primitives for remote A2A agents.
Package a2a provides thin, host-oriented client primitives for remote A2A agents.
Package codebuddy provides the built-in Driver implementation for the CodeBuddy CLI.
Package codebuddy provides the built-in Driver implementation for the CodeBuddy CLI.
Package codex provides the built-in Driver implementation for Codex.
Package codex provides the built-in Driver implementation for Codex.
appserver
Package appserver is a typed client for the codex app-server JSON-RPC protocol over stdio.
Package appserver is a typed client for the codex app-server JSON-RPC protocol over stdio.
Package cursor provides the built-in Driver implementation for the Cursor Agent CLI.
Package cursor provides the built-in Driver implementation for the Cursor Agent CLI.
Package driver defines the SPI (service provider interface) implemented by agent CLI integrations.
Package driver defines the SPI (service provider interface) implemented by agent CLI integrations.
examples
a2a-server command
a2a-server starts an in-process A2A server around a real local Agent, then calls it through the A2A client.
a2a-server starts an in-process A2A server around a real local Agent, then calls it through the A2A client.
inspect command
inspect demonstrates read-only Driver probes and Agent inspection.
inspect demonstrates read-only Driver probes and Agent inspection.
profiles command
profiles materializes a complete provider profile — skills, MCP, hooks, sub-agent, instructions — and then proves on disk that the selected CLI really sees it.
profiles materializes a complete provider profile — skills, MCP, hooks, sub-agent, instructions — and then proves on disk that the selected CLI really sees it.
profiles/hook command
profiles/resources command
profiles/resources shows the resource half of the profile vocabulary: not only *where* the provider profile lives, but *what must exist inside it*.
profiles/resources shows the resource half of the profile vocabulary: not only *where* the provider profile lives, but *what must exist inside it*.
quickstart command
quickstart constructs an Agent from a Driver, asks one question, and reads one Result.
quickstart constructs an Agent from a Driver, asks one question, and reads one Result.
showcases/team-agent-workflow command
Host-side scaffolding for the team-agent-workflow showcase: the temporary task fixture, the workspace stage audit, the terminal renderer, and the protocol text handed to the leader.
Host-side scaffolding for the team-agent-workflow showcase: the temporary task fixture, the workspace stage audit, the terminal renderer, and the protocol text handed to the leader.
skills command
skills proves runtime skill injection end-to-end with a real local CLI: the agent is given a write-proof skill and only follows it if the skill actually reached the provider's skill directory.
skills proves runtime skill injection end-to-end with a real local CLI: the agent is given a write-proof skill and only follows it if the skill actually reached the provider's skill directory.
streaming command
streaming shows the unified typed event channel for one run, consumed with a single for-range + type switch, closed out by Result().
streaming shows the unified typed event channel for one run, consumed with a single for-range + type switch, closed out by Result().
streaming/chat command
streaming/chat is a minimal typed-event chat UI in pure Go.
streaming/chat is a minimal typed-event chat UI in pure Go.
structured-output command
structured-output derives a JSON schema from a Go type, asks the Driver for structured output, validates it, and returns the decoded value with Result.
structured-output derives a JSON schema from a Go type, asks the Driver for structured output, validates it, and returns the decoded value with Result.
threads command
threads demonstrates persistent, resume-only, and forked conversation Threads on host-owned keys.
threads demonstrates persistent, resume-only, and forked conversation Threads on host-owned keys.
threads/codec command
threads/codec looks underneath the Thread abstraction at the driver-owned session codec.
threads/codec looks underneath the Thread abstraction at the driver-owned session codec.
tools command
tools gives a local coding agent one host-defined typed Go function.
tools gives a local coding agent one host-defined typed Go function.
web-chat command
web-chat exposes an Agent over AG-UI Server-Sent Events with a single bridge call.
web-chat exposes an Agent over AG-UI Server-Sent Events with a single bridge call.
web-chat/aguiclient command
web-chat/aguiclient is the minimal-middleware AG-UI demo:
web-chat/aguiclient is the minimal-middleware AG-UI demo:
web-chat/copilotkit command
web-chat/copilotkit combines the SDK's unified Event stream with CopilotKit's React UI through the AG-UI protocol.
web-chat/copilotkit combines the SDK's unified Event stream with CopilotKit's React UI through the AG-UI protocol.
hosttools
a2adelegation
Package a2adelegation provides host-owned Local and Remote delegation for an adaptor Agent.
Package a2adelegation provides host-owned Local and Remote delegation for an adaptor Agent.
sessionrecorder
Package sessionrecorder is an opt-in host utility that records typed agent-adaptor events under a host-owned session key and serves them back by a cursor that stays monotonic across runs.
Package sessionrecorder is an opt-in host utility that records typed agent-adaptor events under a host-owned session key and serves them back by a cursor that stays monotonic across runs.
internal
engine
Package engine hosts private resolution, thread coordination, profile, and runtime-service operations used by the public Agent pipeline.
Package engine hosts private resolution, thread coordination, profile, and runtime-service operations used by the public Agent pipeline.
keycodec
Package keycodec provides a collision-free encoding for composite keys used by internal indexes and lease targets.
Package keycodec provides a collision-free encoding for composite keys used by internal indexes and lease targets.
testutil/apifreeze
Package apifreeze provides stable public API snapshots for contract tests.
Package apifreeze provides stable public API snapshots for contract tests.
toolidentity
Package toolidentity owns the private constants shared by the Agent-owned Tool runtime and provider profile materializers.
Package toolidentity owns the private constants shared by the Agent-owned Tool runtime and provider profile materializers.
toolruntime
Package toolruntime exposes an immutable provider-neutral Tool catalog over a process-wide, authenticated loopback gateway.
Package toolruntime exposes an immutable provider-neutral Tool catalog over a process-wide, authenticated loopback gateway.
Package mcp is the v1 vocabulary for declaring Model Context Protocol (MCP) servers a host attaches to an agent, replacing hand-written configuration structs with one-line constructors:
Package mcp is the v1 vocabulary for declaring Model Context Protocol (MCP) servers a host attaches to an agent, replacing hand-written configuration structs with one-line constructors:
Package memory provides a concurrency-safe, in-memory implementation of threadstore.Store.
Package memory provides a concurrency-safe, in-memory implementation of threadstore.Store.
Package profile defines provider profile selection and profile resource declarations (see docs/api-reference.md §§10–11).
Package profile defines provider profile selection and profile resource declarations (see docs/api-reference.md §§10–11).
Package skill is the consumer-facing vocabulary for agent skills.
Package skill is the consumer-facing vocabulary for agent skills.
Package threadstore defines the storage contract behind stateful Threads (see docs/api-reference.md §13).
Package threadstore defines the storage contract behind stateful Threads (see docs/api-reference.md §13).
Package tool defines provider-neutral tools implemented by Go functions.
Package tool defines provider-neutral tools implemented by Go functions.

Jump to

Keyboard shortcuts

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