agentturn

package module
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Sep 19, 2026 License: MIT Imports: 10 Imported by: 0

README

agentturn

A composable agent loop in Go over Open Responses: one loop, one transcript type, one tool contract, hooks and queues. Everything else is a front that feeds prompts in and consumes events out, or a subscriber.

  • The transcript is openresponses.Items. What a session stores, what the model receives and what a front renders are the same bytes.
  • The model is any openresponses.Streamer: a remote server through Client.AsAdapter, a local adapter, or another agent served by front/responses.
  • The tool contract is its own library, agenttool, so a tool is written once and runs under any loop. The root module depends on openresponses, agenttool and the standard library; adapters with heavier dependencies are nested modules.

Install

go get github.com/ChristopherDavenport/agentturn

Go 1.25 or later.

A tool, a loop, an agent

type ReadFileArgs struct {
	Path     string `json:"path" desc:"Absolute path to read"`
	MaxBytes int    `json:"max_bytes,omitempty" desc:"Stop after this many bytes"`
}

var ReadFile = agenttool.New("read_file", "Read a file from disk",
	func(ctx context.Context, a ReadFileArgs) (string, error) {
		b, err := os.ReadFile(a.Path)
		return string(b), err
	})

cfg := agentturn.Config{
	Name:         "reader",
	Description:  "Answers questions about files on disk.",
	Model:        openresponses.NewClient(baseURL, openresponses.WithAPIKey(key)).AsAdapter(),
	ModelName:    "gpt-5",
	Instructions: "Be brief.",
	Tools:        []agenttool.Tool{ReadFile},
}

// Low-level: an iterator of events. The loop runs ahead of the consumer.
for ev, err := range agentturn.Run(ctx, nil, openresponses.Items{openresponses.UserText("What is in go.mod?")}, cfg) {
	if err != nil {
		log.Fatal(err)
	}
	if u, ok := ev.(*agentturn.ItemUpdate); ok {
		if d, ok := u.Stream.(*openresponses.OutputTextDeltaEvent); ok {
			fmt.Print(d.Delta)
		}
	}
}

// Stateful: queues, subscribers with barriers, abort, idle.
a := agentturn.New(cfg)
a.Subscribe(func(ctx context.Context, ev agentturn.Event) error {
	// every event is a barrier: the loop waits for this to return
	return nil
})
err := a.Prompt(ctx, openresponses.UserText("What is in go.mod?"))

A run is one Prompt or Continue until the agent goes idle; a turn is one model call plus the tool executions it requested. The events of a run, in order:

event carries
run_start run ID
turn_start the exact openresponses.Request sent
item_start, item_update, item_end an item entering the transcript; item_update wraps the wire StreamEvent verbatim
response_end the folded Response with usage, before any tool of the turn runs
tool_start, tool_update, tool_end one tool call from preflight to result, tool_end in completion order
turn_end the folded Response with usage, and the tool results
run_end the items added this run and the reason: done, stopped, input_required, aborted, error

Tools

Tools come from agenttool: agenttool.New[Args, Out] turns a typed function into a tool, reflecting and validating the schema from the argument struct, and agenttool.Executor runs a batch. The loop only knows the agenttool.Tool interface; see that repository for the contract, the schema generator and the MCP adapters.

A batch of calls runs in parallel, bounded, unless the config or a tool asks for sequential execution. Config.BeforeToolCall is the policy seam: block, rewrite arguments, terminate the run, or defer the call to the caller. A deferred call ends the run with input_required and the pending calls listed; Agent.Resume takes their outputs and continues, which is how a front asks a human before a tool runs. AfterToolCall overrides results; ShouldStopAfterTurn ends a run early.

Every other request member comes from Config.Request, the base the loop builds each turn's request on: tool_choice, max_output_tokens, include: reasoning.encrypted_content for reasoning models, and so on. BeforeModelCall sees the finished request before it is sent.

Composition

The loop never learns a sub-agent concept. It knows a Model and a list of Tool, and every composition is one of those two things. A protocol earns a place only with a serve side and a consume side:

protocol serve consume
Open Responses front/responses openresponses.Client.AsAdapter
MCP agenttool/mcpserver agenttool/mcpclient
A2A front/a2a tools/a2a
in-process Agent tools/agent

The MCP row lives in agenttool because MCP is about tools, not about the loop: mcpserver serves any agenttool.Tool, and mcpclient produces them. An agent stands in three places inside another system:

  • As a model. front/responses makes a loop an openresponses.Adapter; openresponses.NewHandler serves it; another loop points its Model at it through Client.AsAdapter.
  • As a tool. tools/agent wraps a Config as a Tool: a child run on a fresh transcript, progress through Call.OnUpdate, the final text as the output and a ChildInfo in Result.Details.
  • As a peer. front/a2a exposes a loop to A2A callers; tools/a2a wraps a remote A2A agent as a Tool.

Config.Name and Config.Description are the single source for how an agent presents itself in every one of these.

Modules

path module depends on
. (agentturn), front/responses, compact, tools/agent root openresponses, agenttool
front/a2a, tools/a2a nested github.com/a2aproject/a2a-go
session nested github.com/ChristopherDavenport/agentsession

compact is the reference Transform: when the transcript exceeds a token budget it calls the model's Compact and splices the returned compaction item in front of the recent tail, caching the result.

c := compact.New(model, compact.WithBudget(60_000))
cfg.Transform = c.Transform

session subscribes an Agent to an agentsession store: items on item_end, the response entry with its request hash on response_end, config entries as settings change, and a link entry for every child run. Because every event is a barrier, a turn's tool preflight waits for the assistant items to be durable.

rec, s, err := session.Start(ctx, store, agentsession.Header{CWD: cwd})
defer rec.Attach(agent)()

Design

The plan is docs/plans/agent-layer.md. Invariants the tests hold:

  • The transcript after a run is a valid Open Responses input: every function_call is answered before the next user message, or the run ended with the pending calls recorded.
  • Exactly one run_end per run, nothing after it.
  • item_end for an assistant item follows output_item.done; partial items never reach subscribers as item_end.
  • Abort cancels the model stream and running tools through the context; the transcript keeps only completed items.
  • Events for one run are delivered from one goroutine.

License

MIT. See LICENSE.

Documentation

Overview

Package agentturn is a composable agent loop over Open Responses: one loop, one transcript type, one tool contract, hooks and queues. Everything else is a front that feeds prompts in and consumes events out, or a subscriber.

The transcript is openresponses.Items. What a session stores, what the model receives and what a front renders are the same bytes. The model is any openresponses.Streamer: a remote server through openresponses.Client.AsAdapter, a local adapter, or another agent served by front/responses.

Vocabulary

A run is one Run, Continue, Agent.Prompt or Agent.Continue until the agent goes idle. A turn is one model call plus the tool executions it requested.

Low-level loop

Run and Continue are observational: they yield Event values in order and the loop does not wait for the consumer between phases.

for ev, err := range agentturn.Run(ctx, transcript, prompts, cfg) {
	if err != nil { ... }
	switch e := ev.(type) {
	case *agentturn.ItemUpdate:
		if d, ok := e.Stream.(*openresponses.OutputTextDeltaEvent); ok {
			fmt.Print(d.Delta)
		}
	}
}

Agent

Agent adds queues, subscribers and run control over the same loop. Subscribers are awaited in registration order and every event is a barrier: tool preflight for a turn does not start until every subscriber has returned for the assistant item, and Agent.Prompt settles only after the run_end subscribers finish.

Composition

The loop never learns a sub-agent concept. It knows a Model and a list of agenttool.Tool, and every composition is one of those two things: front/responses serves a loop as a model, tools/agent wraps a config as a tool, and the A2A and MCP adapters do the same across a protocol.

Index

Constants

View Source
const (
	EventRunStart    = "run_start"
	EventTurnStart   = "turn_start"
	EventResponseEnd = "response_end"
	EventItemStart   = "item_start"
	EventItemUpdate  = "item_update"
	EventItemEnd     = "item_end"
	EventToolStart   = "tool_start"
	EventToolUpdate  = "tool_update"
	EventToolEnd     = "tool_end"
	EventTurnEnd     = "turn_end"
	EventRunEnd      = "run_end"
)

Event type names.

Variables

View Source
var (
	// ErrRunning: Prompt or Continue was called while a run is active.
	ErrRunning = errors.New("agentturn: agent is already running")
	// ErrAborted: the run was aborted with [Agent.Abort] or its context.
	ErrAborted = errors.New("agentturn: run aborted")
	// ErrInputRequired: the last run deferred calls that are still
	// unanswered; [Agent.Resume] with their outputs first.
	ErrInputRequired = errors.New("agentturn: pending tool calls must be resumed before continuing")
	// ErrNotPending: Resume was given an output for a call that is not
	// pending, or left a pending call unanswered.
	ErrNotPending = errors.New("agentturn: output does not answer a pending call")
)

Errors returned by Agent.

View Source
var (
	// ErrNoModel: Config.Model is nil.
	ErrNoModel = errors.New("agentturn: config has no model")
	// ErrCannotContinue: the transcript does not end with a user message
	// or a function call output, so there is nothing for the model to
	// answer.
	ErrCannotContinue = errors.New("agentturn: transcript must end with a user message or a function call output to continue")
	// ErrNoPrompt: Run was called with no prompt items.
	ErrNoPrompt = errors.New("agentturn: no prompt items")
)

Errors returned before a run starts.

Functions

func Continue

func Continue(ctx context.Context, t Transcript, cfg Config) iter.Seq2[Event, error]

Continue drives the loop from the transcript as it stands. The last item must be a user message or a function call output.

func DefaultFilter

func DefaultFilter(t Transcript) openresponses.Items

DefaultFilter drops every item whose type carries a slug prefix such as "agentturn:note", which marks an app-only extension item, and nil items. It is the Filter when Config.Filter is nil.

func Run

func Run(ctx context.Context, t Transcript, prompts openresponses.Items, cfg Config) iter.Seq2[Event, error]

Run appends prompts to the transcript and drives the loop until the agent goes idle. Events are yielded in order; the loop runs ahead of the consumer and never waits between phases. A fatal failure arrives once, as the final pair: a RunEnd with ReasonError together with its error. A misuse before the run starts is yielded as (nil, err) with no events at all. Breaking out of the loop cancels the run.

The transcript is not modified; the items the run appended are on the RunEnd.

func VisibleFilter

func VisibleFilter(visible ...string) func(Transcript) openresponses.Items

VisibleFilter returns a filter like DefaultFilter that keeps the listed extension item types.

Types

type Agent

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

Agent is the stateful loop: a transcript, queues, subscribers and run control over Run. One run at a time; a second Prompt while one is active returns ErrRunning.

Subscribers are called synchronously, in registration order, for every event, so every event is a barrier: the loop does not move to the next phase until each subscriber has returned. A subscriber that returns an error ends the run with ReasonError.

func New

func New(cfg Config, opts ...Option) *Agent

New builds an agent.

func (*Agent) Abort

func (a *Agent) Abort()

Abort cancels the active run, if any. The model stream and running tools see the cancellation through their context and the run ends with ReasonAborted.

func (*Agent) Config

func (a *Agent) Config() Config

Config returns the agent's configuration.

func (*Agent) Continue

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

Continue runs from the transcript as it stands, which must end with a user message or a function call output.

func (*Agent) FollowUp

func (a *Agent) FollowUp(item openresponses.Item)

FollowUp queues an item to be injected when the run would otherwise end, so the agent keeps going instead of going idle.

func (*Agent) Prompt

func (a *Agent) Prompt(ctx context.Context, items ...openresponses.Item) error

Prompt appends items and runs until idle. It returns when the run_end subscribers have returned: nil when the run finished or was stopped, ErrAborted when it was aborted, and the failure otherwise.

func (*Agent) Resume

func (a *Agent) Resume(ctx context.Context, outputs ...*openresponses.FunctionCallOutput) error

Resume answers the calls the last run deferred and continues. Every pending call must have exactly one output, and no output may answer a call that is not pending; a caller that refuses a call answers it with the refusal as text, which the model then sees. The outputs are appended with their item events before the model is called.

func (*Agent) State

func (a *Agent) State() State

State returns a snapshot.

func (*Agent) Steer

func (a *Agent) Steer(item openresponses.Item)

Steer queues an item to be injected after the current tool batch, before the next model call. When the agent is idle it is consumed by the next run at the same point.

func (*Agent) Subscribe

func (a *Agent) Subscribe(fn func(context.Context, Event) error) (unsubscribe func())

Subscribe registers fn for every event and returns a function that removes it. Subscribing during a run takes effect from the next event.

func (*Agent) WaitForIdle

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

WaitForIdle blocks until no run is active or ctx is done.

type Config

type Config struct {
	// Name is how the agent names itself when composed: the tool name in
	// tools/agent, the server name in front/mcp, the agent card in
	// front/a2a.
	Name string
	// Description is one paragraph about the agent, used the same way.
	Description string

	// Model streams responses. Required.
	Model Model
	// ModelName is the model field of every request.
	ModelName string
	// Instructions is the instructions field of every request.
	Instructions string

	// Tools the model may call. The loop reads it at the start of each
	// turn.
	Tools []agenttool.Tool
	// ToolProvider, when set, supplies the tools for each turn in place
	// of Tools, so a source whose tool list changes, such as a remote
	// MCP server, is picked up on the next turn.
	ToolProvider func(ctx context.Context) []agenttool.Tool

	Reasoning openresponses.ReasoningConfig
	Text      openresponses.TextConfig

	// Request is the base of every request the loop sends: tool_choice,
	// parallel_tool_calls, max_output_tokens, temperature, truncation,
	// include, safety_identifier, prompt_cache_key, service_tier and
	// every other member are copied from it. The loop owns input, tools,
	// store, stream and previous_response_id, and ModelName,
	// Instructions, Reasoning and Text take precedence over the same
	// members here when set. Metadata is merged with the run and turn
	// IDs the loop adds.
	Request openresponses.Request

	// BeforeModelCall runs on the fully built request of each turn, just
	// before it is sent and before turn_start reports it. It may change
	// anything; a change to Input has the same effect on session
	// verification as a Transform.
	BeforeModelCall func(context.Context, *openresponses.Request) error

	// ToolExecution selects parallel (default) or sequential batches.
	ToolExecution ExecutionMode
	// MaxParallelTools bounds a parallel batch; zero means
	// agenttool.DefaultMaxParallel.
	MaxParallelTools int
	// MaxTurns stops a run after this many turns with ReasonStopped;
	// zero means no limit.
	MaxTurns int

	// Filter drops app-only items before each model call. nil means
	// [DefaultFilter].
	Filter func(Transcript) openresponses.Items
	// Transform runs before each model call on the whole transcript and
	// may return a shorter or otherwise edited one for that call only:
	// prune, compact, inject context. It receives a copy of the slice
	// and must not mutate the items. The working transcript is not
	// replaced.
	Transform func(context.Context, Transcript) (Transcript, error)

	// BeforeToolCall runs once per call, in the model's order, before any
	// call of the batch executes. A nil decision allows the call.
	BeforeToolCall func(context.Context, ToolCallInfo) (*ToolDecision, error)
	// AfterToolCall runs when a call completes and may replace its
	// result. A nil override keeps the result.
	AfterToolCall func(context.Context, ToolResultInfo) (*ToolOverride, error)
	// ShouldStopAfterTurn ends the run after a turn even when the model
	// requested tools.
	ShouldStopAfterTurn func(context.Context, TurnInfo) (bool, error)

	// RequestExtra is passed through as Request.Extra on every call.
	RequestExtra map[string]any
}

Config describes an agent. The zero value is not usable: Model is required.

func (Config) BaseRequest

func (c Config) BaseRequest(ctx context.Context) openresponses.Request

BaseRequest returns the request every turn starts from: Config.Request with the loop-owned transport members set (store false, stream true, no previous_response_id), ModelName, Instructions, Reasoning and Text applied over it, RequestExtra merged over its Extra, and the tool definitions of the moment. Input and the per-turn metadata are added by the loop; a recorder uses this to write the initial settings.

type Event

type Event interface {
	EventType() string
}

Event is one step of a run. Concrete types are RunStart, TurnStart, ItemStart, ItemUpdate, ItemEnd, ResponseEnd, ToolStart, ToolUpdate, ToolEnd, TurnEnd and RunEnd. Decoded values are pointers, so switch on *ItemUpdate and so on.

type ExecutionMode

type ExecutionMode int

ExecutionMode selects how a batch of tool calls runs.

const (
	// Parallel runs the calls of a batch concurrently, bounded by
	// [Config.MaxParallelTools], unless a tool in the batch is
	// agenttool.Sequential.
	Parallel ExecutionMode = iota
	// Sequential runs every batch one call at a time in the model's order.
	Sequential
)

type ItemEnd

type ItemEnd struct {
	RunID string
	Turn  int
	Item  openresponses.Item
	// ResponseID is the ID of the response that produced the item, and
	// empty for an item the loop appended itself.
	ResponseID string
}

ItemEnd carries a completed item. For an assistant item it is emitted only after output_item.done; partial items never arrive here. The item is in the transcript when this event is delivered.

func (*ItemEnd) EventType

func (*ItemEnd) EventType() string

EventType returns "item_end".

type ItemStart

type ItemStart struct {
	RunID string
	Turn  int
	Item  openresponses.Item
	// ResponseID is the ID of the response streaming the item, and empty
	// for an item the loop appended itself.
	ResponseID string
}

ItemStart announces an item entering the transcript: a prompt or queued message, an assistant item as the stream opens it, or a function call output. For an assistant item the Item is the live accumulated value and fills in as updates arrive.

func (*ItemStart) EventType

func (*ItemStart) EventType() string

EventType returns "item_start".

type ItemUpdate

type ItemUpdate struct {
	RunID      string
	Turn       int
	Item       openresponses.Item
	Stream     openresponses.StreamEvent
	ResponseID string
}

ItemUpdate carries one wire event for an assistant item. Stream is the openresponses event verbatim, so a front switches on the same concrete types it would use against a remote server. Item is the accumulated item so far.

func (*ItemUpdate) EventType

func (*ItemUpdate) EventType() string

EventType returns "item_update".

type Model

type Model = openresponses.Streamer

Model is anything that can stream an Open Responses response.

type Option

type Option func(*Agent)

Option configures a new Agent.

func WithTranscript

func WithTranscript(t Transcript) Option

WithTranscript starts the agent from an existing transcript, as when resuming a session.

type Reason

type Reason string

Reason says why a run ended.

const (
	// ReasonDone: the model produced a final answer with no tool calls
	// and no queued follow-ups.
	ReasonDone Reason = "done"
	// ReasonStopped: ShouldStopAfterTurn, a terminating tool batch or
	// MaxTurns ended the run.
	ReasonStopped Reason = "stopped"
	// ReasonInputRequired: BeforeToolCall deferred one or more calls to
	// the caller; RunEnd.Pending lists them and the run continues once
	// their outputs are appended (see Agent.Resume).
	ReasonInputRequired Reason = "input_required"
	// ReasonAborted: the context was cancelled.
	ReasonAborted Reason = "aborted"
	// ReasonError: the model, a hook or a subscriber failed; RunEnd.Err
	// says which.
	ReasonError Reason = "error"
)

Run end reasons.

type ResponseEnd

type ResponseEnd struct {
	RunID    string
	Turn     int
	Response *openresponses.Response
}

ResponseEnd carries the folded response of a turn, usage included, as soon as the stream ends and before any tool of the turn runs. Its output items have all been delivered with item_end. A response that failed is delivered here too, before the run ends with the error, so a recorder can write it.

func (*ResponseEnd) EventType

func (*ResponseEnd) EventType() string

EventType returns "response_end".

type RunEnd

type RunEnd struct {
	RunID  string
	Items  Transcript
	Reason Reason
	// Err is set when Reason is ReasonError, and to the context error
	// when Reason is ReasonAborted.
	Err error
	// Pending lists the function calls a deferred decision left
	// unanswered when Reason is ReasonInputRequired. The transcript is
	// a valid input again once each has a function_call_output.
	Pending []*openresponses.FunctionCall
}

RunEnd closes a run. Exactly one is emitted per run and nothing follows it. Items are the items the run appended to the transcript.

func (*RunEnd) EventType

func (*RunEnd) EventType() string

EventType returns "run_end".

type RunStart

type RunStart struct {
	RunID string
}

RunStart opens a run.

func (*RunStart) EventType

func (*RunStart) EventType() string

EventType returns "run_start".

type State

type State struct {
	// Transcript is a copy of the slice; items are shared.
	Transcript Transcript
	Running    bool
	RunID      string
	Turn       int
	// Steering and FollowUps count the queued items.
	Steering  int
	FollowUps int
	// Pending lists the deferred calls awaiting outputs; Prompt and
	// Continue refuse until Resume has answered them.
	Pending []*openresponses.FunctionCall
}

State is a snapshot of the agent.

type ToolCallInfo

type ToolCallInfo struct {
	RunID string
	Turn  int
	// Call is the function_call item as the model produced it.
	Call *openresponses.FunctionCall
	// Tool is the tool that will run, or nil when no tool has that
	// name; the call then fails with an error output unless the hook
	// blocks it first.
	Tool agenttool.Tool
	// Args are the arguments as raw JSON.
	Args json.RawMessage
}

ToolCallInfo describes a call before it runs.

type ToolDecision

type ToolDecision struct {
	// Block refuses the call. The model sees Reason as the error output.
	Block bool
	// Defer hands the call to the caller instead of running it: the
	// other calls of the batch proceed, no output is appended for this
	// one, and the run ends with ReasonInputRequired listing it. The
	// caller appends the output later and continues. Block wins when
	// both are set.
	Defer bool
	// Reason is the message the model sees when Block is set.
	Reason string
	// Terminate hints the loop to stop after the batch, as a tool result
	// would.
	Terminate bool
	// Args, when non-nil, replaces the arguments the tool receives.
	Args json.RawMessage
}

ToolDecision is a hook's verdict on a call.

type ToolEnd

type ToolEnd struct {
	RunID    string
	Turn     int
	CallID   string
	Name     string
	Result   agenttool.Result
	Err      error
	Blocked  bool
	Deferred bool
}

ToolEnd carries a finished call, in completion order. Err is set when the tool failed, the arguments were invalid or no tool had the name; Blocked is set when BeforeToolCall refused the call. In both cases Result holds the error output the model sees. Deferred is set when BeforeToolCall handed the call to the caller: nothing ran, Result is empty and no output is appended.

func (*ToolEnd) EventType

func (*ToolEnd) EventType() string

EventType returns "tool_end".

type ToolOverride

type ToolOverride struct {
	Result agenttool.Result
	Err    error
}

ToolOverride replaces the result of a call.

type ToolResultInfo

type ToolResultInfo struct {
	RunID  string
	Turn   int
	Call   *openresponses.FunctionCall
	Tool   agenttool.Tool
	Args   json.RawMessage
	Result agenttool.Result
	Err    error
}

ToolResultInfo describes a completed call.

type ToolStart

type ToolStart struct {
	RunID  string
	Turn   int
	CallID string
	Name   string
	Args   json.RawMessage
}

ToolStart announces a tool call after preflight, in the model's order.

func (*ToolStart) EventType

func (*ToolStart) EventType() string

EventType returns "tool_start".

type ToolUpdate

type ToolUpdate struct {
	RunID   string
	Turn    int
	CallID  string
	Name    string
	Partial agenttool.Result
}

ToolUpdate carries progress from a running tool.

func (*ToolUpdate) EventType

func (*ToolUpdate) EventType() string

EventType returns "tool_update".

type Transcript

type Transcript = openresponses.Items

Transcript is the conversation as the model sees it, plus app-only items that the Config.Filter removes before each call.

type TurnEnd

type TurnEnd struct {
	RunID       string
	Turn        int
	Response    *openresponses.Response
	ToolResults []agenttool.Result
}

TurnEnd closes a turn with the folded response, usage included, and the tool results in the model's order.

func (*TurnEnd) EventType

func (*TurnEnd) EventType() string

EventType returns "turn_end".

type TurnInfo

type TurnInfo struct {
	RunID    string
	Turn     int
	Response *openresponses.Response
	// ToolResults are the results of this turn's calls in the model's
	// order, empty when the model called no tools.
	ToolResults []agenttool.Result
	// Transcript is the working transcript after the turn.
	Transcript Transcript
}

TurnInfo describes a finished turn.

type TurnStart

type TurnStart struct {
	RunID   string
	Turn    int
	Request openresponses.Request
}

TurnStart opens a turn and carries the exact request sent to the model.

func (*TurnStart) EventType

func (*TurnStart) EventType() string

EventType returns "turn_start".

Directories

Path Synopsis
Package compact is the reference compaction Transform for agentturn: when a transcript grows past a token budget, the older part is folded into a compaction item by the model's own compaction endpoint and the recent part is kept verbatim.
Package compact is the reference compaction Transform for agentturn: when a transcript grows past a token budget, the older part is folded into a compaction item by the model's own compaction endpoint and the recent part is kept verbatim.
front
responses
Package responses serves an agent as an Open Responses server: the loop as an openresponses.Adapter.
Package responses serves an agent as an Open Responses server: the loop as an openresponses.Adapter.
a2a module
session module
tools
agent
Package agent wraps an agent configuration as a tool, so one loop can delegate to another in process.
Package agent wraps an agent configuration as a tool, so one loop can delegate to another in process.
a2a module

Jump to

Keyboard shortcuts

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