dago

package module
v0.0.0-...-94a2dde Latest Latest
Warning

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

Go to latest
Published: Aug 24, 2026 License: MIT Imports: 41 Imported by: 0

README ¶

dago

dago is an idiomatic Go implementation of the Deep Agents SDK and the focused LangChain/LangGraph behavior it needs. It provides a provider-neutral tool loop, middleware, required delta channels, durable checkpoints, virtual filesystems, inline and background subagents, context compaction, skills, memory, and streaming without trying to reproduce either framework in full.

The public API is currently pre-1.0.

Try the shelley-in-dago browser demo.

Install

go get github.com/semistrict/dago

dago requires Go 1.26 or newer.

Interactive coding agent

dacode is a terminal coding agent with durable threads and goals, streaming tool activity, workspace-aware instructions and skills, and review gates for file writes and shell commands. It uses Bubble Tea, Bubbles, and Lip Gloss for its terminal interface.

go install github.com/semistrict/dago/cmd/dacode@latest
dacode

Run the TUI directly without installing it:

go run github.com/semistrict/dago/cmd/dacode@latest

From a dago source checkout, use go run ./cmd/dacode instead.

On first run, dacode opens OpenAI subscription sign-in and stores its refreshable session under the user configuration directory. Set OPENAI_API_KEY to use API-key authentication instead; an explicit key takes precedence over the saved session. Inside the terminal, /auth (or /connect) opens the credential manager. API-key input is masked and subscription sign-in can be cancelled without accepting a late callback. Credential changes apply to newly built model runtimes; they never silently retarget an in-flight agent.

dacode config lists canonical configuration keys, effective values, and sources. Remote execution is an explicit application capability. Builds that register provider factories can use --sandbox PROVIDER, --sandbox-id ID, --sandbox-snapshot-name NAME, and a workspace-contained --sandbox-setup FILE. A bare --sandbox uses sandboxes.default only after that explicit flag; configuration alone never creates a remote resource. The stock binary lists the curated provider contract but fails closed until an authenticated provider factory is linked. Run dacode doctor for bounded offline installation diagnostics, or dacode doctor --json for a stable machine-readable report. Credential values and provider URL paths, queries, user information, and fragments are omitted. dacode install NAME checks the build's closed optional-integration catalog. Current releases already ship every listed extra as Go package source, so the command reports the package or API to import and configure without changing the host. An application must still import the integration and rebuild; the command does not add it to the running dacode binary. --package refuses every name because this build has no separately loadable package format and never downloads an arbitrary Go module. dacode update CHANNEL ARTIFACT --manifest-base URL --public-key /absolute/key.pub performs a signed release check; add --dry-run to download and verify the artifact without writing, or --apply to replace the current executable. There is deliberately no built-in release URL or trust key yet: both must be supplied explicitly, manifests must carry a valid Ed25519 signature, artifacts must match the signed SHA-256 and Go build identity, and development or locally replaced builds cannot be activated. See docs/UPDATES.md for the manifest contract and platform notes. For interactive use, pass the same trust inputs as --update-channel, --update-artifact, --update-manifest-base, and --update-public-key; then bare /update opens the signed-update modal and /auto-update controls the persisted preference. /notifications configures dependency warnings, Ctrl+N opens pending actions, and /trace opens the active LangSmith thread only when a stored credential and an official trusted web endpoint are configured. config get KEY, config path, config set KEY VALUE, and config unset KEY provide deterministic text or --json output and manage the owner-private versioned configuration file. Runtime precedence is default, config file, canonical environment variable, DEEPAGENTS_CODE_ override, DEEPAGENTS_CLI_ override, then an explicit command-line flag. An explicitly empty prefixed string shadows the canonical value. Credentials are never printed or accepted by config set; keep them in the environment or existing sign-in store. Use --config PATH or DACODE_CONFIG to select another file.

Normal coding-agent launches also resolve environment files with shell exports first, the nearest .env found from --cwd second, and ~/.deepagents/.env last. Project files cannot replace process-launch, proxy, TLS, tracing-endpoint, MCP-trust, automatic review, or terminal-identity controls; ignored key names are reported without their values. Files, lines, keys, values, ancestor search, and the final environment are bounded, and symbolic-link environment files are rejected.

Applications can opt into owner-private structured debug traces with DEEPAGENTS_CODE_DEBUG=1. DEEPAGENTS_CODE_DEBUG_FILE selects an absolute file inside an owner-private directory, and DEEPAGENTS_CODE_LOG_LEVEL accepts DEBUG, INFO, WARNING, or ERROR. Trace files are bounded and common credential attributes are redacted, but messages can still contain sensitive application data and should be reviewed before sharing.

On macOS, model-driven shell commands first run under the native process sandbox. It permits workspace and temporary-directory writes, denies network access, and reports policy violations as a structured approval boundary. Auto mode reviews only commands that cross that boundary; workspace-contained commands continue without a review call. The execute tool describes this policy and accepts sandbox_permissions: "require_escalated" with a concise justification when the model knows a command needs to run outside it; that request is reviewed before the command runs. The checkout containing the starting directory is writable, including its validated Git administration directories, so commits and other Git operations work from linked worktrees. Workspace-confined file mutations proceed without reviewer latency in Auto mode, while direct file access to protected metadata remains denied; external tool gates still use direct approval rules. The read-only reviewer defaults to gpt-5.6-luna, falls back to the active model only when that implicit default cannot be resolved, and can be overridden with --approval-model. --manual-review requires a user decision for every gated action, and --yolo bypasses review and the local process boundary. The first successful Auto-mode enable shows a versioned safety notice: Enter keeps Auto and records the notice in the private local state directory, while Esc returns to Manual without recording it. The first YOLO entry is gated more strictly: YOLO remains inactive until Enter successfully persists the current warning policy; m selects Manual and Esc keeps the prior mode. The active approval mode is also stored per durable thread under a SHA-256-derived key. Resuming a thread restores its own mode, and live Shift+Tab or slash-command changes are persisted before they take effect. Missing, invalid, or unreadable thread records use Manual. The server consults the same record for gated actions in both the main agent and delegated subagents, so UI state alone cannot enable unrestricted work. At a Manual approval prompt, the warning-bordered menu shows numbered Approve, thread-Auto, and Reject choices for one call or a batch. Arrow keys or j/k move the cursor, Enter selects, 1/2/3 select by position, y approves, a enables Auto (or returns an Auto fallback to Manual), n or Esc rejects, and Tab opens a single-line rejection-reason field. Long shell commands can be expanded with e; write, edit, delete, and other tools receive bounded purpose-specific previews, while recognized credential-file contents are hidden from both the prompt and tool row. Enter submits a rejection reason (or a bare rejection when blank), while Esc or n first closes the field without deciding. If a gated action arrives within two seconds of composer input, the decision keys stay attached to the draft until typing becomes idle; the approval is revealed after at most 30 seconds even if typing continues. The same deferral applies when Auto review falls back to a user decision.

/auto model selects the current session's classifier, Ctrl+S persists the default, and /auto model clear returns to the main model. Auto assesses the complete pending tool-call batch through a required structured decision tool and requires exact tool-call ID coverage. Malformed or unavailable reviews deny conservatively before bounded consecutive, total-denial, or configuration-fault thresholds return control to the user. A distinct classifier receives only bounded, redacted trusted-user context and summarized action metadata, never assistant text or raw tool results.

Use -n 'task' for one-shot operation, pipe a task to standard input, or pass --stdin to require piped input explicitly. --quiet prints only the final response, --no-stream buffers it, and --json emits one versioned result object. For unattended work, --max-turns N and --timeout SECONDS bound execution and exit with status 124 when the bound is reached; the default turn bound is 50. --recursion-limit N separately bounds graph steps within each turn and defaults to 2000. Use -m 'task' to submit an initial interactive prompt, or -s NAME to invoke a project skill around the initial interactive or one-shot request. Runtime skill precedence, from lowest to highest, is built-ins, enabled plugin skills, the selected agent profile, ~/.agents/skills, project .deepagents/skills, project .agents/skills, ~/.claude/skills, and project .claude/skills. --startup-cmd CMD runs a local setup command in the workspace before skill discovery and before the first model turn. Its literal, bounded output stays local rather than entering model context; non-zero exits warn and continue, while cancellation stops startup. Use dacode skills list|info|create|delete to manage user or --project skills, and dacode skills trust list|add|revoke|clear to manage exact external-symlink targets. In the TUI, /skills lists the effective catalog, /skill:NAME [task] invokes one skill, and /remember and /skill-creator invoke the standard authoring skills. An untrusted external symlink opens an exact-target approval prompt; declining does not read its instructions. The built-in deepagents-thread-inspector uses the read-only dacode skills inspect-thread JSON workflow for bounded local summaries, transcripts, and latest-turn inspection. Use dacode plugin list|install|uninstall|enable|disable and dacode plugin marketplace list|add|remove to manage the owner-private plugin store. plugins is an alias for the same non-interactive command. In the TUI, /plugins opens the Discover, Installed, and Marketplaces views; keyboard actions install, enable, disable, uninstall, add, or remove entries and then offer a reload. /reload atomically refreshes reloadable environment/configuration values and rebuilds plugin skills, hooks, MCP connections, and web credentials without discarding the current runtime if rebuilding fails. Installed plugins are enabled by default and take effect on the next process, ACP session, or successful reload: skills are qualified as plugin@marketplace:skill, MCP server names are scoped to the plugin, and declared lifecycle hooks execute as trusted host commands. Plugin installation therefore grants instruction, process, and network authority; inspect the publisher and pinned revision before enabling one. Use -r ID to resume a durable thread and --cwd PATH to select the workspace. Run dacode resume to choose a session before opening the TUI, or dacode resume ID to resume a known session. Inside the TUI, /threads opens the same picker. Selected sessions restore their transcripts and approval mode before continuing. Before any transcript is loaded, a session owned by another agent or original working directory requires an explicit switch/stay decision. Threads above the configured context threshold also offer an exact-checkpoint compaction choice. /offload (alias /compact) runs that same bounded compactor directly and commits its state only after summary generation succeeds.

The first interactive launch offers a keyboard-driven setup flow and stores its completion marker and selected preferences in the private state directory. /restart is available when the process owns an explicitly configured local development server; it opens a confirmation modal and reports restart failures without exposing the child process or its environment. /agents opens the named-agent picker. Put an agent's instructions in <state-dir>/<name>/AGENTS.md; each agent loads and updates only that durable memory, and switching starts a new thread. Arrow keys or Tab move through the picker, Enter switches, Ctrl+S toggles the startup default, and Esc cancels. The built-in dacode agent remains available and creates an empty memory file on first use. -a NAME selects or creates a profile directly; without it, startup uses agents.default, then a valid agents.recent, then the built-in profile. Each profile also has private skills/ and sessions/ namespaces, and session browsing is restricted to the selected agent. Use dacode agents list to inspect profiles and dacode agents reset --agent NAME [--target SOURCE] [--dry-run] to restore the built-in prompt or copy another profile's prompt. Reset replaces the destination profile, including its skills and session namespace; preview it before use when that state matters. Pass --memory-auto-save=false, or set DEEPAGENTS_CODE_MEMORY_AUTO_SAVE=false, to load memory in reference-only mode without asking the model to persist new learnings. /docs, /changelog, and /feedback open the project documentation, releases, and issue form in the active browser environment. Use /editor or Ctrl+X to edit the current draft with $VISUAL, then $EDITOR, or the platform's default text editor. Saving a blank draft cancels the edit. Use /effort to choose one of the active model profile's reasoning levels, /effort LEVEL to set one directly, or /effort clear to restore the provider default. The selected level is saved per model and shown beside the model name. Use /theme to preview and select the full built-in color catalog. Arrow keys or Tab preview, Enter saves the global choice, Esc restores the prior theme, n toggles labels and canonical keys, and t saves the highlighted theme for the current TERM_PROGRAM. Terminal mappings override the global choice, while DEEPAGENTS_CODE_THEME overrides both. Custom [themes.NAME] tables in ~/.deepagents/config.toml require a label, may set dark, and may override any semantic color with #RRGGBB; ansi-dark and ansi-light preserve the terminal palette instead of imposing a background. The composer completes slash commands and @ workspace paths, turns valid dropped images and videos into bounded structured attachments, persists non-command history, collapses large pastes until submission, and accepts messages while a turn is running by queueing them. Prefix a draft with ! to run it in the local shell and include its bounded output as context for the next request; !! runs it locally without adding the command or output to model context. Shift/Alt/Ctrl+Enter inserts a newline. Draft action buttons clear or copy the current input.

On macOS, local file tools are confined to the workspace and expose it as virtual /. Shell commands start in the real working directory; the native policy permits host reads but confines writes to the active checkout, its validated Git metadata, and temporary directories until an exact boundary crossing is approved. Other local platforms currently retain unrestricted host paths. Remote sandbox sessions use the provider's working directory and cannot access local host paths.

The transcript renders streamed Markdown, lifecycle-styled tool rows, grouped tool summaries, skill invocations, and bounded inline write/edit diffs. Ctrl+O expands or collapses the latest eligible message, tool row, skill, or tool group. /line-numbers toggles gutters for newly created diffs and persists the preference; PageUp hydrates older rows when a long restored transcript is using its sliding render window.

When the agent needs information it cannot infer, it can pause the active turn with one or more text or multiple-choice questions. Enter confirms an answer, Tab and Shift+Tab move between questions, every choice list includes a free-form Other entry, and Esc dismisses the prompt. Required answers cannot be blank. Ctrl+X edits the focused free-form answer in the configured external editor. Completed question rows show only User answered or Question failed; answer text remains in the durable model transcript but is excluded from automatic-review audit input.

--shell-allow-list recommended makes approved read-only commands execute inline while rejecting every other shell request instead of pausing for review. Pass a comma-separated list such as recommended,git,gh to add trusted executables. --shell-allow-list all explicitly removes shell-command checks; use it only in an isolated environment. One-shot runs expose no shell tool unless a shell allow-list is supplied.

MCP servers are discovered from ~/.deepagents/.mcp.json, then the project's .deepagents/.mcp.json, then project-root .mcp.json; later same-name definitions win. --mcp-config PATH selects one explicit file instead. User and explicit servers connect at startup. Project servers require a definition-bound remembered approval, an operator-controlled process allow-list, or the explicit per-run --trust-project-mcp flag. Unapproved or disabled project entries do not connect. Configured tool names use SERVER_TOOL, support allow/deny patterns, and retain MCP read-only annotations for headless approval policy. OAuth-declared servers remain disconnected until the separate login flow supplies credentials:

dacode mcp login <server>

The command accepts --mcp-config PATH for one explicitly trusted file; otherwise it uses the same definition-bound project trust gate and precedence as startup. Slack uses its workspace-aware public-client flow, GitHub Copilot MCP uses its device flow, and other HTTPS endpoints use MCP dynamic registration with PKCE. Authorization can open the platform browser or use --no-browser; paste-back input remains bounded. Tokens are stored outside MCP configuration under ~/.deepagents/.state/mcp-tokens/ with private permissions and are reused only by the same server name and exact endpoint on a later startup. The login does not mutate a currently running tool registry.

Within the terminal, /mcp opens the current server/tool viewer. Enter expands tools, starts login, or shows a bounded error; F2 stages a server enable/disable change for this session. /mcp login NAME starts the same endpoint-bound OAuth policies and /mcp reconnect rebuilds the idle runtime. Login and enablement changes remain pending until reconnect succeeds; Esc defers them without discarding the pending state.

Use /goal <objective> for work that should continue across turns until complete or blocked. The agent drafts observable acceptance criteria first; accept, edit, reject with feedback, or cancel that proposal in the review panel. Accepted criteria remain visible with the durable goal and are evaluated before a requested completion is committed. /goal show, /goal amend <feedback>, /goal pause, /goal resume, /goal clear, and /goal budget <tokens|clear> control the persisted goal. /goal model and /goal max-iterations are aliases for its rubric grader settings. Active goals resume automatically when the thread becomes idle. Pass --goal TEXT to open the same review flow at interactive startup.

Use /workflows to open the live workflow control panel. It shows background run status, current phase, agent progress, and errors; use the arrow keys to select a run and c to cancel it. /workflow <saved-name-or-script-path> launches a saved workflow directly. Names resolve from .claude/workflows and .agents/workflows in the workspace, while explicit paths are restricted to the workspace and application state directories.

Use /rubric set <criteria> for a persistent quality gate, /rubric next <criteria> for one turn, or /rubric file <path> to load a UTF-8 criteria file. /criteria is an alias. /rubric show, /rubric clear, /rubric model, and /rubric max-iterations inspect and tune grading. For one-shot execution, combine -n TASK with --rubric 'criteria' or --rubric @path; optional --rubric-model and --rubric-max-iterations select the grader behavior.

Use dacode acp (or --acp) to serve the coding agent to an ACP-compatible editor over standard input and output. The editor owns the session and permission prompts in this mode; --yolo remains available to bypass mutating-tool approval gates. Each editor session gets its own workspace runner and any declared stdio, HTTP, or SSE MCP servers. HTTP headers are forwarded for per-session MCP authentication.

--serve-xtermjs serves the same PTY-backed TUI on a loopback-only web address and prints its URL. Use --xtermjs-address HOST:PORT to select a specific loopback listener.

For an explicitly managed local development companion, pass an absolute executable with --local-dev-server PATH. Repeat --local-dev-arg VALUE for literal arguments and select its loopback readiness origin/path with --local-dev-endpoint and --local-dev-health-path. The child receives only a typed, non-credential configuration payload and a small platform environment; additional non-secret names require an explicit --local-dev-inherit-env NAME. The process tree is stopped when either interactive or one-shot execution exits. This opt-in supervisor is unavailable in ACP server mode.

Use the repository-root GitHub Action for bounded CI tasks, durable cache-backed agent memory, and optional skills-repository installation. See ACTION.md for its inputs, secure defaults, and a pinned workflow example.

Managed-agent project scaffold

dago init [name] creates the pinned managed-agent starter layout: agent.json, AGENTS.md, an empty tools.json, .gitignore, an example skill, and a researcher subagent. When the name is omitted, the command prompts for it. Existing directories are left untouched unless --force is explicit; force refreshes only the starter files and preserves unrelated content.

Bare dago no longer starts an interactive chat. Run dacode for the interactive coding agent; dago is reserved for explicit project and managed-service commands.

dago init my-agent
cd my-agent

Managed workspaces can also list, inspect, and explicitly delete remote agents. Authentication resolves LANGSMITH_API_KEY before LANGCHAIN_API_KEY; the endpoint resolves the corresponding LANGSMITH_ENDPOINT / LANGCHAIN_ENDPOINT variables and otherwise uses the hosted API. Only HTTPS origins are accepted.

dago agents list
dago agents get --include-files AGENT_ID
dago agents delete AGENT_ID

Deletion prompts unless --yes is supplied.

Deploy the current scaffold with dago deploy. The first run creates a remote agent; later runs patch metadata and synchronize only the managed AGENTS.md, tools.json, skills/, and subagents/ directory projection. The remote ID is pinned outside the checkout under ~/.deepagents/deployments/, keyed by the project’s absolute path and authenticated endpoint.

Creation uses a stable server idempotency key and recovery marker derived from the authenticated endpoint and required project-owned extras.dago_deployment_id. dago init generates that identifier and preserves it during forced scaffold refreshes. To make --reset create a genuinely new remote agent, rotate the identifier in agent.json first; this keeps the new logical creation explicit and portable.

dago deploy --dir ./my-agent --dry-run
dago deploy --dir ./my-agent

--detach skips the health request, --reset forgets cached state and creates a new agent, and --yes acknowledges an agent_id explicitly declared by agent.json. A declared remote must already carry this project's deployment identity; the client will not race to adopt an unbound agent. Dry runs require no credential and perform no state or network I/O.

The same authenticated workspace can manage its MCP server registry. Identifiers accept an exact ID, unique name, or normalized URL. Static headers are supplied explicitly and redacted from inspection output; OAuth records can be registered without storing a token in the project.

dago mcp-servers list
dago mcp-servers add --name tools --header X-Api-Key=VALUE https://tools.example
dago mcp-servers add --auth-type oauth --connect --no-browser https://oauth-tools.example
dago mcp-servers get tools
dago mcp-servers update tools --url https://new-tools.example
dago mcp-servers connect --no-browser tools
dago mcp-servers tools tools
dago mcp-servers delete tools

Tool discovery prints a paste-ready tools.json snippet. OAuth connection registers the workspace provider, prints its HTTPS verification URL, optionally opens the platform browser, and performs bounded long polling; use repeated --scope, --force-new, --timeout, or --no-browser as needed. Deletion prompts unless --yes is explicit.

Use dago as a library

Models implement the small damodel.Chat interface, and tools implement datool.Tool. This complete example uses the OpenAI adapter and a typed local tool; the agent and tool APIs remain provider-neutral:

package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/semistrict/dago"
	"github.com/semistrict/dago/dagent"
	"github.com/semistrict/dago/daproviders/openai"
	"github.com/semistrict/dago/datool"
)

type addInput struct {
	A int `json:"a" description:"First number"`
	B int `json:"b" description:"Second number"`
}

func main() {
	chat := openai.NewAPIKey(os.Getenv("OPENAI_API_KEY"), "gpt-5", openai.Options{
		ContextWindow: 128_000,
	})
	add := datool.New("add", "Add two integers.", func(_ context.Context, input addInput) (int, error) {
		return input.A + input.B, nil
	})

	agent := dago.New(chat,
		dago.WithSystemPrompt("Use tools when they help answer accurately."),
		dago.WithTools(add),
	)
	result, err := agent.Invoke(context.Background(), dagent.Prompt("What is 17 plus 25?"))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(result)
}

Filesystem tools are opt-in through dago.WithFilesystem. With the default state backend, files live in the agent’s files delta channel, are isolated by thread, and become durable when a checkpoint saver is configured. Pass an explicit store, composite, local-shell, or remote sandbox backend when the agent should operate elsewhere.

Agent-owned facilities use that same backend automatically. Configure them as values instead of constructing middleware with a duplicate backend argument:

compiled := dago.New(chat,
	dago.WithBackend(workspace),
	dago.WithSkills(dago.Skills{Sources: []string{"/skills"}}),
	dago.WithMemory(dago.Memory{Sources: []string{"/AGENTS.md"}}),
)

Memory sources use the backend's virtual paths. Machine-managed onboarding blocks inside those files are protected automatically, including for subagents that share the filesystem. Set Memory.ReadOnly to use the built-in reference-only prompt while still loading the configured files.

Durable goals are an opt-in agent facility and require a checkpoint saver. The middleware exposes create_goal, get_goal, get_rubric, and constrained update_goal tools; dagoal.Service provides host-owned pause, resume, budget, objective, criteria, and clear operations. When accepted criteria must gate goal completion, place dagoal.RubricCompletionMiddleware before dago.Rubric so a model-requested completion is committed only after a satisfied verdict:

goalOptions := dagoal.Options{}
compiled := dago.New(chat,
	dago.WithMiddleware(
		dagoal.Middleware(goalOptions),
		dagoal.RubricCompletionMiddleware(dago.RubricStatusKey, string(dago.RubricSatisfied)),
		dago.Rubric(chat, dago.RubricOptions{}),
	),
	dago.WithSaver(saver),
)
goals := dagoal.NewService(compiled, goalOptions)

Binary media is returned opaquely by default. Supplying dago.WithFilesystem can configure a VideoExtractor, which changes video read_file pagination to seconds and returns sampled JPEG frames. davideo.NewFFmpeg is the optional ready-made implementation; the FFmpeg executable remains an external deployment dependency.

Declarative subagents use the same functional options as top-level agents. A nil model inherits the parent model, and tools inherit unless WithTools overrides them:

researcher := dago.NewSubagent(
	"researcher",
	"Researches a topic and returns a concise answer.",
	nil,
	dago.WithSystemPrompt("Research the delegated topic."),
	dago.WithTodo(),
)
compiled := dago.New(chat, dago.WithSubagents(researcher))

They always receive tool-call repair and inherit parent facilities that were explicitly enabled for declarative children, including filesystem, interpreter, memory, summarization, approval, and prompt caching. Precompiled graphs can be registered with NewRunnableSubagent; only delegation options such as WithInheritedState apply because their construction is already complete. Human approval, including approval inside a subagent, requires a checkpoint saver so the exact pending tool call can resume without replaying completed sibling tools.

dacode also discovers declarative subagents from NAME/AGENTS.md directories. Project definitions under .deepagents/agents override same-name definitions in the selected agent profile's agents directory. Frontmatter requires description, may set name and model, and the remaining Markdown is the subagent system prompt. An omitted or empty model inherits the main model. Defining general-purpose replaces the built-in general agent; otherwise the built-in remains available.

Workflows

Workflows are an optional extension that lets a model launch a deterministic JavaScript orchestration script in the background. The host supplies a daworkflow.AgentRunner, which is the policy boundary for models, reasoning effort, custom agent types, structured output, and worktree isolation. The manager owns cancellation and same-session replay and should be closed with its application scope:

manager := daworkflow.NewManager(runner, daworkflow.Options{
	SessionDirectory: sessionDir,
})
defer manager.Close()

compiled := dago.New(chat,
	dago.WithMiddleware(daworkflow.Middleware(manager)),
)

The workflow tool accepts an inline script, a resolver-backed saved name or script_path, or a completed resume_from_run_id, and immediately returns task and run IDs. Scripts begin with a runtime-evaluated export const meta = {...} declaration and can use agent, parallel, pipeline, phase, log, args, budget, and one level of nested workflow calls. The runtime has no filesystem or Node APIs and rejects implicit clocks and randomness. Concurrency, agent count, collection size, memory, execution time, and tokens are bounded through daworkflow.Options. When SessionDirectory is set, the manager persists the script, per-agent transcripts, replay journal, and final JSON result under that directory. Options.Completed can bridge terminal runs into the host application's native task-notification channel.

The terminal host implements isolation: "worktree" for local Git workspaces. Each isolated agent call starts from the configured workspace's committed HEAD on a new workflow/agent-* branch. A clean checkout is removed after the call; an unchanged branch is removed, a committed branch is retained, and a checkout with uncommitted changes is retained and reported as an agent failure with its recovery path. Worktree isolation is a coordination boundary rather than a security sandbox, and it is not available when the terminal host is using a remote or custom backend.

Type-safe tools

datool.New derives an object schema from the handler's input struct, validates model arguments, and decodes them before calling the handler:

type weatherInput struct {
	Location string `json:"location" description:"City and state" jsonschema:"minLength=1"`
	Units    string `json:"units,omitempty" jsonschema:"enum=celsius|fahrenheit,default=celsius"`
}

weather, err := datool.New("weather", "Get the current weather.", func(ctx context.Context, input weatherInput) (string, error) {
	return input.Location + ": sunny", nil
})

Fields use encoding/json names and omitempty behavior. A description tag sets field documentation; jsonschema supports requirements, formats, enums, defaults, examples, string/array/object lengths, patterns, and numeric bounds. Handlers that need call state can use datool.RuntimeFromContext(ctx). Returning a datool.Result preserves its full content, artifact, state update, interrupt, and handoff; strings become text results and other values become JSON text. Runtime schema details can be layered onto the generated schema with functional options such as WithPropertyType, WithPropertyEnum, WithPropertyValue, WithPropertySchema, WithoutProperty, or the lower-level WithTransformSchema.

Web tools

The opt-in daweb package provides http_request and HTML-to-Markdown fetch_url tools. Supplying a Tavily key also enables web_search; a blank key leaves that tool out of the returned set:

webClient := daweb.NewClient(daweb.Options{})
tools := daweb.Tools(webClient, os.Getenv("TAVILY_API_KEY"))
compiled := dago.New(chat, dago.WithTools(tools...))

The client accepts only HTTP and HTTPS URLs, rejects credentials and non-public address ranges, pins each connection to its validated DNS answers, revalidates every redirect, ignores environment proxies, and bounds request, response, rendered page, redirect, and timeout resources. Library applications opt in explicitly. The coding agent includes fetch_url by default and prefers a model provider's hosted web-search tool, including OpenAI and Anthropic integrations. OpenAI search is enabled by default; --model-params '{"web_search":false}' disables it. When the resolved model does not provide web search, dacode auth set tavily or TAVILY_API_KEY supplies an approval-gated local fallback. Stored service credentials take precedence over environment values. If both are configured, provider-hosted search wins and the local web_search tool is not exposed.

Typed adapters keep the state and checkpoint wire formats flexible without requiring application assertions. Use dagent.Field with a dagent.FieldSpec[T] to declare typed reducers, datool.StateAs[T] for tool state, and dagent.DepsAs[T] or datool.DepsAs[T] for application dependencies supplied through WithDependencies. dagent.ResumeAs[T] accepts both live Go values and checkpoint-restored plain JSON values. Structured results can be declared with dagent.StructuredOutputFor[T] and decoded with dagent.StructuredAs[T]; the latter validates against the schema derived from T. damessage.MetadataAs[T] and damessage.SetMetadata provide the same typed boundary for raw JSON metadata maps.

dagent.RuntimeModel consumes the model configurable value, resolves it through a required caller-owned ModelResolver, swaps only that invocation's model, and persists the selected spec in private thread state unless Ephemeral is requested. The resolver retains ownership of provider clients, credentials, caching, and any network access; the middleware bounds the model spec and contains resolver panics.

External local event ingress is opt-in through daeventbus. Supply the sink and an absolute Unix socket path positionally, then run the source under an owning context:

source := daeventbus.NewUnixSource(sink, socketPath, daeventbus.Options{})
err := source.Run(ctx)

Each newline-delimited JSON object carries kind (command, prompt, or signal), payload, and optional bypass and correlation_id fields. The source replies once per line with an ACK or bounded NACK. It only validates and forwards events: the application-owned sink decides what any command, prompt, signal, or bypass hint means. Unix ingress reports an explicit unsupported error on Windows rather than silently opening another transport.

Owned agent streams support for event, err := range stream.Events(). Model streams support for chunk, err := range stream.Chunks(). Both iterators close their stream on completion, error, or early loop exit; Next and Close remain available for explicit control. Applicable built-in Anthropic harness profiles resolve from the model's provider and identifier. The full Nemotron 3 Ultra repair, retry, progress-budget, tool-selection, entity-resolution, and answer-completeness stack is available explicitly from daproviders/nemotron. Provider construction defaults for OpenAI, NVIDIA, and OpenRouter are available as an explicit daproviders/profile.Profiles value. daproviders/profile.Resolver composes those profiles with caller-owned provider factories to resolve provider:model strings without hiding credential or optional dependency ownership. Model-spec matching normalizes known provider aliases, and Bedrock detection covers provider-prefixed and Amazon Nova identifiers.

Full provider selection is available from daproviders/modelconfig. It combines the pinned provider catalog, stored/environment credential precedence, paired base URLs, model parameters, profile overrides, retries, and owner-private default/recent preferences while keeping provider factories explicit. See model configuration. dacode exposes --model-params, --profile-override, --max-retries, --default-model, and --clear-default-model; selecting an integration not compiled into the application fails explicitly without network or package discovery.

--model claude_agent:sonnet selects the compiled Claude CLI provider. It uses print-mode bidirectional stream JSON, disables local customization and every built-in tool except Skill, and exposes only the current agent request's tools through an ephemeral authenticated loopback MCP server. Effective skills are materialized in a temporary session plugin, and an MCP tool description larger than Claude's inline limit becomes a generated skill with a short loading instruction. The outer dago agent executes MCP tools and returns their results while the same CLI process remains alive; partial text and reasoning events stream through dacode as they arrive. Native JSONL reconstruction and --resume are used only after a process restart. See model configuration for the isolation boundary and supported parameters.

--model anthropic:MODEL selects the direct Messages API provider. Hosted web search is enabled by default, and hosted_tools, mcp_servers, betas, plus forward-compatible top-level Messages parameters can be supplied with --model-params.

Local Ollama model discovery is explicit and credential-free. Supply the HTTP transport and endpoint positionally, then call Discover when a local model picker or configuration flow needs a refresh:

discovery := ollama.NewDiscovery(http.DefaultTransport, "", ollama.DiscoveryOptions{})
models, err := discovery.Discover(ctx)

An empty endpoint uses http://127.0.0.1:11434. Discovery accepts only literal loopback HTTP(S) origins (the exact localhost name is rewritten to a literal), performs one bounded /api/tags request, sorts and deduplicates names, and never adds authentication. It is not invoked automatically by the agent or provider resolver.

LangSmith LLM Gateway routing is similarly explicit and provider-neutral. Supply a caller-owned model factory and gateway key positionally; an empty endpoint uses the managed gateway:

gateway := langsmithgateway.NewResolver(factory, "", gatewayKey, langsmithgateway.Options{})
model, err := gateway.ResolveModel(ctx, "openai:gpt-4.1")

The factory receives the routed endpoint, key, and original model specification and remains responsible for provider SDK construction and network policy. The built-in pinned routes cover Anthropic, Baseten, Fireworks, Google GenAI, and OpenAI. Construction and endpoint inspection perform no I/O.

JavaScript interpreter

Enable a persistent, sandboxed QuickJS-ng REPL with Interpreter. The js_eval tool supports top-level await, console output, functions and variables that persist through checkpoints, and concurrent programmatic tool calls. It runs the exact quickjs-rs 0.2.5 WASM guest under Wazero's interpreter backend, including in Go browser-WASM builds. TinyGo builds exclude the Wazero-backed implementation; enabling Interpreter in a TinyGo build fails during agent construction, and the Shelley TinyGo application omits js_eval from its tool catalog.

compiled := dago.New(chat,
	dago.WithSaver(saver),
	dago.WithInterpreter(dago.Interpreter{
		PTC:             []string{"read_file", "glob", "grep", "search"},
		PTCTransparency: true,
	}),
)

The first memory image is checkpointed as an anchor. The generated QuickJS guest uses WAFL-style 4 KiB write barriers, so subsequent checkpoints copy only dirty memory pages. A nil PTC allowlist exposes only read_file, glob, and grep; an empty non-nil list disables PTC. Explicitly allowlisted tools execute inside js_eval and do not pass through model-tool approval middleware, so mutating tools should only be included when that direct authority is intended. PTCTransparency defaults to false. When enabled, each tools.* invocation emits the ordinary streamed tool lifecycle with its arguments, output, status, and parent js_eval call ID. User interfaces and protocol adapters can therefore render PTC calls like model-originated tool calls without adding them to model-visible history.

OpenAI adapter

The focused Responses API adapter supports text and multimodal messages, tool calls, parallel tool calls, JSON Schema structured output, token streaming, usage, prompt caching metadata, API keys, and an explicit subscription OAuth session. Standard OpenAI endpoints use persistent Responses WebSocket connections by default and send incremental input on compatible successive turns. Set ResponsesWebSocket to new(false) to force HTTP; compatible custom endpoints can opt in with new(true). Standard endpoints also enable remote server-side compaction by default: at 90% of ContextWindow (or 200,000 tokens when it is unknown), the adapter sends a compaction-trigger Responses request, preserves its encrypted state, and resumes the turn. Set ServerCompaction to new(false) to disable it or set CompactionThreshold to override the trigger point.

chat := openai.NewAPIKey(os.Getenv("OPENAI_API_KEY"), "gpt-5", openai.Options{
	ContextWindow: 128_000,
})

The core package never discovers credentials or chooses a provider. OAuth token persistence is opt-in and writes only to the caller-provided private file.

OpenRouter adapter

The OpenRouter adapter uses OpenRouter's Responses API and preserves the same text, multimodal, tool-calling, structured-output, reasoning, web-search, usage, and streaming contracts as the OpenAI adapter. It also supports optional app attribution and provider routing:

chat := openrouter.New(os.Getenv("OPENROUTER_API_KEY"), "anthropic/claude-sonnet-4.6", openrouter.Options{
	AppURL:   "https://example.com/my-agent",
	AppTitle: "My Agent",
	Routing: &openrouter.ProviderRouting{
		Ignore:         []string{"azure"},
		DataCollection: "deny",
	},
	ContextWindow: 200_000,
})

BaseURL defaults to https://openrouter.ai/api/v1. Credentials remain explicit; the adapter does not read environment variables itself.

Durable execution

saver, err := sqlite.Open("agent-checkpoints.sqlite")
if err != nil {
	log.Fatal(err)
}
defer saver.Close()

compiled := dago.New(chat, dago.WithSaver(saver))
result, err := compiled.Invoke(ctx,
	dagent.FromCheckpoint(dacheckpoint.Config{ThreadID: "conversation-1"}),
	dagent.Prompt("Inspect the project."),
)

Agents expose checkpoint history, replay, thread fork, and thread deletion. SQLite and PostgreSQL savers match the supported Python table layouts and delta-snapshot rules. Cross-language payload compatibility is intentionally limited to the safe plain-data subset in docs/SERIALIZATION.md; Python-specific object records are rejected with typed context instead of reconstructed.

Long-running agent host

datalon is an experimental, provider-neutral host for local assistants that stay running across channel messages and scheduled jobs. It owns one runtime, any number of channel adapters, and an optional scheduler; starts and stops them in dependency order; serializes work per channel conversation; and lets /stop cancel the active turn and discard turns already queued behind it. Different conversations can still make progress concurrently.

The zero-value configuration uses the current working directory, a 500-step recursion limit, finite message/send/shutdown bounds, and private assistant state at ~/.deepagents/default/. Set a stable assistant ID to isolate another state tree. Passing a nil runtime deliberately selects the echo runtime, which makes channel and scheduler integration testable before a model-backed runtime is configured.

Channel tool approval is an experimental convenience for a trusted operator, not a production authorization boundary. datalon/approval.FromEnvironment parses the comma-separated DEEPAGENTS_TALON_INTERRUPT_ON_TOOLS overlay with finite limits; listed local or MCP tool names are exact and always override a same-name disabled base rule. Apply the resulting rules to the main agent and inherited subagents, then resolve every human_approval interrupt through the invocation's channel handler:

policy, err := approval.FromEnvironment(nil, approval.Options{})
if err != nil {
	return err
}
rules := policy.ApprovalRules(applicationRules...)
agent := dago.New(chat, dago.WithApprovalRules(rules...))

// In the runtime's bounded invoke/resume loop:
resume, err := approval.ResolveInterrupt(ctx, request, result.Interrupts[0])

WithApprovalRules carries the combined rules into dago's built-in general-purpose and declarative subagents. A separately compiled or remote subagent is a separate execution boundary and must receive the same policy itself. Handlerless scheduled runs, timeouts, cancellation, transport errors, malformed requests, invalid replies, and unsupported decisions all fail closed. Only a recognized reply from the exact origin channel conversation and initiating sender resolves one pending approval; spoofed, stale, duplicate, or ordinary messages remain on the serialized agent path.

Fleet exports can be materialized into an explicit assistant state directory before starting the host:

go run ./cmd/datalon import-fleet <fleet-export.zip> <assistant-state-dir>

The importer writes AGENTS.md, skills/, and remapped agents/<name>/AGENTS.md prompts. Fleet tools.json files are import input only, and config.json is ignored. Requested remote tools produce a credential-free OAuth .mcp.json plus a human-readable .mcp.json.setup handoff. The completion summary recommends a DEEPAGENTS_TALON_INTERRUPT_ON_TOOLS value when the export marked tools for approval. Repeated imports refresh only these importer-managed paths and preserve unrelated assistant runtime state.

datalon/mcp loads the resulting MCP configuration without reading credentials from it. Resolution checks DEEPAGENTS_TALON_MCP_CONFIG, then MCP_CONFIG, then ~/.deepagents/.mcp.json. HTTP, SSE, and trusted local stdio servers are supported, including allow/deny tool patterns and per-server load status. Applications supply their HTTP policy and may connect the discovered tools to any model-backed runtime:

oauth := mcp.NewOAuthFactory(httpClient, tokenStore, interaction)
loader := mcp.NewClient(httpClient, oauth, mcp.Options{})
tools, configPath, err := loader.LoadDiscovered(ctx, nil, "")
defer tools.Close()

Applications that need the pinned provider policies can instead use oauthpolicy.NewFactory: Slack uses its public client with PKCE, state validation, and optional workspace selection; GitHub Copilot MCP uses its public device flow; all other HTTPS servers retain standards-based metadata discovery and dynamic client registration. The required HTTP client, token store, and UI-agnostic interaction are still supplied by the application.

OAuth tokens stay in a caller-selected private token store. The command-line flow uses ~/.deepagents/.state/mcp-oauth/ and paste-back authorization, so it does not need to open a browser or own a listener:

go run ./cmd/datalon mcp config
go run ./cmd/datalon mcp login <server>

datalon/cron adds a versioned cron/jobs.json store, a minute-granularity persistent scheduler, and conversation-scoped create_job, list_jobs, edit_job, and remove_job tools. One-shot and recurring jobs are claimed on disk before they run, so a restart cannot repeat the same interval. Each run persists its last status or bounded error and emits talon_event JSON lifecycle records; results beginning with [SILENT] deliberately skip delivery.

datalon/lifecycle applies bounded retention to sensitive assistant state. Its zero options preserve completed cron records for 30 days, remove inbound media after 24 hours, and enforce the pinned 1 GiB global artifact ceiling. State root and cron store are required positionally; construction performs no I/O. Operators can preview the same plan without deletion:

retention := lifecycle.New(config.StateDir(), cronStore, lifecycle.Options{})
preview, err := retention.DryRun(ctx)
report, err := retention.Clean(ctx)

Reports expose only counts and hashed audit references, never prompts, paths, filenames, content, or job IDs. The entire finite walk is validated before file deletion, linked and special state fails closed, cron replacement remains atomic, and cleanup secures managed state owner-only. Durable channel sessions and remote traces are preserved unless the caller explicitly opts a confined local artifact directory into retention; session deletion additionally requires a static risk acknowledgement. See datalon/lifecycle.

Per-run LangSmith tracing is opt-in through datalon/tracing. The provider-neutral wrapper preserves the runtime result even when tracing fails, bounds copied inputs, outputs, errors, and metadata, and records channel or scheduler metadata on one root run per invocation. The environment helper follows the Talon opt-in contract: LANGSMITH_TRACING must be truthy and LANGSMITH_API_KEY must be non-empty.

Long-running applications can use tracing.NewManager for the broader coding-agent policy. A required credential store is resolved once against a caller-supplied environment snapshot; a stored key enables tracing unless a recognized flag opts out, agent traces receive their own project, the original tracing variables can be restored for shell subprocesses, and orphaned tracing fails closed. Region aliases, bounded replica projects, and replica ingestion endpoints are supported without mutating process-global environment. Configuration.ResolveSink passes credentials only to a required caller-owned provider factory, and tracing.NewManaged redacts known credential values while emitting the primary and replica spans.

langsmithClient := langsmith.NewClient()
defer langsmithClient.Close()
runtime = tracing.NewFromEnv(
	runtime,
	langsmithtrace.New(langsmithClient),
	config.AssistantID,
	nil,
	tracing.Options{},
)

The zero options use project deepagents-talon, run name talon.agent, and finite payload and completion bounds. The application owns endpoint policy, credentials, client shutdown, and flushing.

tracing.NewURLResolver separately resolves a project web URL through a required caller lookup, caches only validated HTTPS results with finite timeout/TTL/count bounds, and builds credential-free thread links. It never opens a browser; terminal or headless presentation remains an application concern.

Inbound voice transcription is opt-in through datalon/speech. Wrap any channel that supplies a confined local voice_path or media_path; voice and video messages receive the transcript while ordinary files pass through unchanged. NewLocal defaults to nvidia/parakeet-tdt-0.6b-v3 on CPU, converts a private bounded copy to 16 kHz mono WAV with ffmpeg, and invokes the optional local Transformers pipeline through python3. Set the device to cuda for compatible local hardware. For a non-Parakeet model, NewOpenAI requires the caller's HTTP client, API key, and model positionally and uses the bounded audio-transcription endpoint. The environment parser also accepts legacy SPEECH_ENABLED and SPEECH_DEVICE values.

Telegram is an additive Bot API channel. Its token and HTTP client are required positional dependencies; construction performs no network work. Long polling is the default, uses finite request/retry/payload limits, and can persist its update offset:

telegramChannel := telegram.New(
	os.Getenv("TELEGRAM_BOT_TOKEN"),
	http.DefaultClient,
	telegram.Options{
		Exposure: telegram.AllowlistExposure(
			[]string{"123456789"},
			[]string{"-1001234567890"},
		),
	},
)
host := datalon.NewHost(runtime, config, telegramChannel)

Private messages are selected by user ID, channel posts by chat ID, and group or supergroup traffic is ignored. telegram.SelfExposure requires operator IDs; telegram.OpenExposure requires the exported risk acknowledgement. The alternate telegram.NewWebhook constructor requires its webhook secret positionally and returns an http.Handler, while the application continues to own TLS, routing, listener lifecycle, source-address policy, and webhook registration.

WhatsApp is an additive channel backed by the packaged Node bridge. The bridge binds only to loopback, requires bearer authentication, persists pairing state in an owner-private directory, and reports qr_pending while its operator QR is shown on standard output. The application supplies an authenticated transport and stable session directory positionally and owns the Node process lifecycle:

whatsappTransport := whatsapp.NewHTTPTransport(
	"http://127.0.0.1:3000",
	os.Getenv("WHATSAPP_BRIDGE_TOKEN"),
	whatsapp.HTTPOptions{},
)
whatsappChannel := whatsapp.New(
	whatsappTransport,
	"/private/operator/whatsapp-session",
	whatsapp.Options{},
)

Self-only exposure is the default; allowlists accept exact conversations or case-sensitive mention patterns, and open exposure requires an explicit risk acknowledgement. Outbound chunks carry a bot header. Media is hard-capped at 64 MiB and staged only from a caller-confined outbound root. See datalon/whatsapp for bridge setup and security boundaries.

Agent Client Protocol

daacp exposes an agent to ACP-compatible editors over newline-delimited JSON-RPC. The process must reserve standard output for protocol messages; send logs to standard error.

server := daacp.New(compiled, daacp.Options{
	Name:    "workspace-agent",
	Version: "1.0.0",
})
if err := server.Serve(ctx, os.Stdin, os.Stdout); err != nil {
	log.Fatal(err)
}

The adapter supports ACP v1 session creation and durable loading with replay-marked human, assistant, and tool history. A load is accepted only when its absolute working directory matches the directory stored with the original session. Factory-backed servers created with daacp.NewFactory can advertise model choices: changing the model Session Config Option rebuilds that session's runner with the selected model in daacp.AgentSessionContext while retaining its checkpointed conversation. With durable loading enabled, the replacement runner also persists the selection through daacp.SessionConfigSaver, and session/load restores it before replaying history. Only advertised model identifiers reach the factory. dacode acp advertises the startup model first, followed by its supported OpenAI model choices.

The adapter also supports prompts, cancellation, close, authentication handshakes, session configuration negotiation, streamed text and reasoning, tool status and progress, plans, and approve/reject permission requests. A session factory can construct an isolated runner from the requested working directory and MCP declarations; stdio, HTTP, and SSE MCP transports are supported by dacode. The session working directory is also available to tools as daacp.ConfigurableCWD. Additional roots, client filesystem/terminal delegation, and ACP-routed MCP transport are not advertised.

LangSmith Studio

dago dev exposes configured Go agent factories through the LangGraph Agent Server protocol, persists development threads and store values in SQLite, watches Go/module/config/environment files, and rebuilds the server when they change.

go install github.com/semistrict/dago/cmd/dago@latest

Export a factory that accepts the server-owned runtime. Using its saver and store is required for Studio state, history, replay, and thread operations to address the same durable data as agent runs:

func NewAgent(_ context.Context, runtime daserver.Runtime) (*dagent.Agent, error) {
	return dago.New(chat,
		dago.WithSaver(runtime.Saver),
		dago.WithStore(runtime.Store),
		dago.WithDependencies(runtime.Deps),
	), nil
}

Point dago.json at the package and exported factory:

{
  "graphs": {
    "agent": {
      "path": "./agent:NewAgent",
      "description": "Workspace agent"
    }
  },
  "env": ".env"
}

Then start the API and Studio:

dago dev

The default API is http://localhost:2024; --no-browser, --host, --port, --config, and --n-jobs-per-worker are available. Development data and the generated wrapper stay under the ignored .dago_api directory. The examples/studio configuration is a network-free smoke test:

dago dev -c examples/studio/dago.json

This is a focused local Studio integration, not a claim that arbitrary LangGraph applications can run in Go. Its supported Agent Server resources and current limits are listed in docs/COMPATIBILITY.md.

Packages

Package Purpose
dago Deep Agent constructor plus filesystem, JavaScript interpreter, subagent, summary, skill, memory, profile, and rubric middleware
dagent Provider-neutral model/tool graph, middleware lifecycle, approval, retry, todo, streaming, and checkpoint operations
dagoal Durable goal state, model tools, host lifecycle controls, accounting, and continuation messages
dacost Bounded streaming token accounting, provider/model/purpose reports, and local pricing catalogs
damessage, damodel, datool, dastate Stable public contracts and reducers
damodel/modeltest Scripted and prompt-driven predictable model doubles for offline tests and examples
dabackend State, memory, host filesystem, namespaced store, composite, explicit local shell, native macOS process sandbox, structured policy violations, and reusable execute+upload sandbox backends
dabackend/docker Owned local Docker sandbox with a confined workspace, hardened defaults, resource limits, and lifecycle cleanup
dabackend/langsmith Adapter for an existing LangSmith sandbox using langsmith-go
dabackend/runloop Transport-neutral Runloop devbox sandbox and explicit lifecycle/blueprint provider
dabackend/daytona Transport-neutral Daytona sandbox with bounded session-log polling and native batch transfer
dabackend/modal Transport-neutral adapter for an existing Modal sandbox
dabackend/vercel Transport-neutral adapter for an existing Vercel Sandbox
dabackend/agentcore Transport-neutral AgentCore Code Interpreter sandbox and explicit non-reconnectable session provider
dasandbox Explicit remote-provider registry, capability metadata, setup, attach/create ownership, and bounded cleanup
dabackend/contexthub Persistent Context Hub agent-repository files with linked-entry and parent-commit support
dacheckpoint Saver contract and in-memory implementation
daeval, daeval/harbor, daeval/clbench Deterministic behavioral, sandbox-benchmark, and continual-learning evaluation contracts
damanaged Bounded managed-project loading, deployment, directory synchronization, listing, inspection, and deletion client
daplugin Bounded plugin/marketplace manifests, materialization, lifecycle state, discovery, and component composition
datalon, datalon/approval, datalon/mcp, datalon/mcp/oauthpolicy, datalon/telegram, datalon/whatsapp, datalon/cron, datalon/lifecycle, datalon/tracing, datalon/speech Experimental long-running host, channel tool approval, MCP loading/provider OAuth, bounded channels, persistent scheduler, sensitive-state retention, per-run tracing, and opt-in voice transcription
browser/... Reusable browser WebAssembly filesystem, IndexedDB checkpoint, promise bridge, just-bash, directory-handle, and WebGPU adapters; see browser/README.md
dacheckpoint/sqlite, dacheckpoint/postgres Python-schema-compatible durable savers
dastore, dastore/sqlite, dacache Namespaced data store and cache contracts and implementations
daproviders/anthropic Direct Anthropic Messages API with hosted tools, remote MCP, and native SSE
daproviders/claudeagent Persistent isolated Claude CLI model with caller-owned tools over MCP
daproviders/openai Focused Responses API adapter and credential flows
daproviders/nemotron Opt-in Nemotron harness profiles and model-output repair middleware
daproviders/profile Explicit provider-construction profiles, model-spec resolution, provider matching, and Bedrock detection
daproviders/modelconfig Multi-provider catalog, credentials/endpoints, model options, caller factories, and default/recent preferences
daproviders/ollama Explicit, bounded, local-only Ollama model discovery
daproviders/langsmithgateway Explicit provider-neutral LangSmith LLM Gateway route resolution
daweb Opt-in SSRF-hardened HTTP request, page-fetching, and Tavily search tools
davideo Video extraction contracts and optional bounded FFmpeg adapter
daacp Agent Client Protocol v1 server adapter for editor integration
daagentprotocol Agent Protocol background-subagent client
daeventbus Opt-in bounded newline-delimited external event ingress over a private Unix socket
daprofilecfg JSON/YAML-safe harness-profile configuration
daconfig Canonical layered configuration, bounded owner-private file management, and typed server environment payloads
daskill Agent Skills parsing, precedence, exact-target symlink trust, built-ins, read-only thread inspection, validation, and rendering contracts
damcp Bounded MCP config discovery, environment resolution, and definition-bound project trust policy
dasubagent Bounded, confined discovery and precedence for filesystem-defined declarative subagents
daworkspace Shared workspace-instruction discovery, scoped guidance summaries, conventional directory filtering, and opt-in local environment context middleware for explicit sandboxes
daserver Embeddable LangGraph Agent Server protocol for LangSmith Studio and SDK clients

The graph runtime is internal. dago claims compatibility only for the Deep Agents surface documented in docs/COMPATIBILITY.md, not general LangChain or LangGraph compatibility.

Docker sandbox

dabackend/docker creates and owns a container from an image that is already available to the local Docker daemon. It never pulls an image implicitly. The image must provide /bin/sh and sleep.

sandbox, err := docker.New(ctx, "my-agent-sandbox:local", docker.Options{})
if err != nil {
	log.Fatal(err)
}
defer sandbox.Close()

compiled := dago.New(chat, dago.WithBackend(sandbox))

By default the container has no network, a read-only root filesystem, no Linux capabilities, no-new-privileges, bounded memory/CPU/PIDs, a writable /tmp, and one private workspace bind mount. Set Network, resource fields, User, or WritableRoot explicitly when the workload requires broader authority. Closing the backend forcibly removes its container and its automatically created workspace.

Examples

Security

Shell execution is never granted by a plain backend. dabackend.LocalShell runs trusted host processes and is not isolation. Filesystem permissions are code-enforced and cannot constrain shell commands, so an application must use an isolated sandbox or omit execute when path-level permissions are required. See docs/SECURITY.md before exposing an agent or the web example.

The core project is MIT licensed. The copied and modified shelley-in-dago example is Apache-2.0 licensed. See NOTICE for attribution and additional notices.

Documentation ¶

Index ¶

Constants ¶

View Source
const (
	// ManagedMemoryBlockStart begins the machine-owned portion of a memory file.
	ManagedMemoryBlockStart = "<!-- deepagents:onboarding-name:start -->"
	// ManagedMemoryBlockEnd ends the machine-owned portion of a memory file.
	ManagedMemoryBlockEnd = "<!-- deepagents:onboarding-name:end -->"
)
View Source
const (
	RubricKey            = "rubric"
	RubricStatusKey      = "_rubric_status"
	RubricIterationsKey  = "_rubric_iterations"
	RubricEvaluationsKey = "_rubric_evaluations"
	RubricRunIDKey       = "_current_grading_run_id"
	RubricActiveKey      = "_active_rubric"
	RubricGraderSource   = "rubric_grader"
)
View Source
const AsyncTasksKey = "async_tasks"
View Source
const FilesystemDeleteDescription = `` /* 157-byte string literal not displayed */
View Source
const FilesystemEditDescription = `` /* 189-byte string literal not displayed */
View Source
const FilesystemGlobDescription = `` /* 134-byte string literal not displayed */
View Source
const FilesystemListDescription = `` /* 196-byte string literal not displayed */
View Source
const FilesystemWriteDescription = `` /* 211-byte string literal not displayed */
View Source
const SubagentResponseFormatConfigKey = "subagent_response_format"

SubagentResponseFormatConfigKey selects a structured-output format for the declarative subagent launched by a task call. The configurable value must be a dagent.StructuredOutput or *dagent.StructuredOutput.

Variables ¶

View Source
var FilesystemReadDescription = fmt.Sprintf(filesystemReadDescriptionTemplate,
	"By default, it reads up to 100 lines starting from the beginning of the file.",
	"- For images and PDFs, omit offset and limit.",
)
View Source
var FilesystemReadVideoDescription = fmt.Sprintf(filesystemReadDescriptionTemplate,
	"For text files, by default it reads up to 100 lines starting from the beginning of the file.",
	"- For images and PDFs, omit offset and limit.\n- For videos, offset and limit are seconds; the default window is 100 seconds.",
)

Functions ¶

func AsyncSubagents ¶

func AsyncSubagents(subagents []AsyncSubagent, options ...AsyncSubagentsOption) dagent.Middleware

AsyncSubagents adds tools for starting and managing durable background tasks.

func ConversationSubagentTool ¶

func ConversationSubagentTool(store ConversationSubagentStore, runner ConversationSubagentRunner, workingDirectory func() string, parentConversationID, modelID string, optionValues ...ConversationSubagentOptions) datool.Tool

ConversationSubagentTool creates a tool that delegates work to named, persistent child conversations.

func GLM52TerminalStallRecovery ¶

func GLM52TerminalStallRecovery() dagent.Middleware

GLM52TerminalStallRecovery returns the one-shot recovery middleware for a headless harness. Callers should not install it in interactive agents, whose tool-free responses can be intentional.

Recovery is deliberately limited to the measured Fireworks GLM-5.2 model. A normalized max-token response containing exactly one assistant message, no tool call, and no structured result is retried once with reasoning disabled and a required tool choice. All other models and response shapes pass through.

func LoadHarnessProfilePlugins ¶

func LoadHarnessProfilePlugins(plugins ...HarnessProfilePlugin) []error

LoadHarnessProfilePlugins invokes explicitly supplied plugins in order. A returned error or panic is captured for that plugin and does not prevent later plugins from loading. Registrations completed before a failure remain registered, matching the additive plugin contract.

func ManagedMemoryGuard ¶

func ManagedMemoryGuard(backend dabackend.Backend, guardedPath string, additionalPaths ...string) dagent.Middleware

ManagedMemoryGuard protects machine-owned blocks in the supplied memory paths. The backend and guarded paths are required inputs; paths use the same virtual namespace as filesystem tools. The returned middleware is safe to share with subagents that share the backend.

The guard must run inside the filesystem middleware so runtime-backed backends have already been bound. NewAgent arranges that ordering automatically for Memory.Sources.

func New ¶

func New(model damodel.Chat, options ...Option) *dagent.Agent

New constructs a deep agent. It panics when static construction options violate an invariant; invocation and dependency failures remain errors on Agent methods.

func PatchToolCalls ¶

func PatchToolCalls() dagent.Middleware

PatchToolCalls repairs assistant tool calls that have no matching result before a resumed agent run. Interrupted turns can otherwise leave model history that providers reject because a requested tool was never answered.

func RegisterHarnessProfile ¶

func RegisterHarnessProfile(key string, profile Profile) error

RegisterHarnessProfile additively registers a provider or provider:model harness profile. An incoming profile layers on top of an existing profile under the same key. Registration is safe to call concurrently and stores a defensive copy.

Registered profiles layer over built-ins during agent construction, while profiles passed with WithProfiles remain caller-owned and have final precedence.

func Rubric ¶

func Rubric(model damodel.Chat, options RubricOptions) dagent.Middleware

Rubric grades natural agent completions and, when necessary, injects actionable feedback before routing back to the model. It panics when static options violate an invariant.

func RubricWithRepository ¶

func RubricWithRepository(model damodel.Chat, repositoryBackend dabackend.Backend, repositoryOptions darepository.Options, options RubricOptions) dagent.Middleware

RubricWithRepository constructs a rubric grader with bounded, read-only access to repositoryBackend. Repository dependencies are explicit and positional; zero repository options select conservative defaults.

func SanitizeSubagentSlug ¶

func SanitizeSubagentSlug(slug string) string

SanitizeSubagentSlug converts a user label to a lowercase ASCII slug.

func Subagents ¶

func Subagents(subagents []Subagent, options ...SubagentsOption) dagent.Middleware

Subagents adds the task tool. Each invocation receives only its task message and a distinct thread identity, preventing parent and sibling state leaks.

func SummarizationTool ¶

func SummarizationTool(model damodel.Chat, backend dabackend.Backend, toolOptions SummarizationToolOptions) dagent.Middleware

SummarizationTool exposes opt-in manual conversation compaction. It shares the private event format used by Summarization but never compacts in the background. It panics when static options violate an invariant.

func ToolExclusion ¶

func ToolExclusion(names []string) dagent.Middleware

ToolExclusion removes profile-excluded tools at the final model boundary, after custom middleware has had an opportunity to alter the request. It intentionally leaves the executor registry intact so historical or resumed tool calls retain the same behavior as the canonical middleware.

func Version ¶

func Version() string

Version returns the installed module version recorded by the Go toolchain. Development builds that do not carry a module version report "development".

Types ¶

type ArgumentTruncationOptions ¶

type ArgumentTruncationOptions struct {
	TriggerTokens   int
	TriggerMessages int
	TriggerFraction float64
	KeepTokens      int
	KeepMessages    int
	KeepFraction    float64
	MaxLength       int
	PreviewLength   int
	TruncationText  string
}

type AsyncCancelRequest ¶

type AsyncCancelRequest struct {
	ThreadID string
	RunID    string
}

AsyncCancelRequest identifies one background run to cancel.

type AsyncCheckRequest ¶

type AsyncCheckRequest struct {
	ThreadID string
	RunID    string
}

AsyncCheckRequest identifies one background run to inspect.

type AsyncFailure ¶

type AsyncFailure struct{ Message string }

AsyncFailure carries a provider-neutral failure message.

type AsyncOutcome ¶

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

AsyncOutcome is the closed result union for a terminal async run.

type AsyncRun ¶

type AsyncRun struct {
	ThreadID string
	RunID    string
	Status   string
	Outcome  AsyncOutcome
}

AsyncRun is the provider-neutral status returned by a background-agent runner.

type AsyncStartRequest ¶

type AsyncStartRequest struct {
	GraphID     string
	Description string
}

AsyncStartRequest identifies the remote graph and initial task.

type AsyncSubagent ¶

type AsyncSubagent struct {
	Name        string
	Description string
	GraphID     string
	Runner      AsyncSubagentRunner
}

AsyncSubagent binds a model-visible agent type to an explicit runner.

type AsyncSubagentRunner ¶

AsyncSubagentRunner adapts a hosted or local background-agent service.

type AsyncSubagentsOption ¶

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

AsyncSubagentsOption configures background-agent middleware.

func WithAsyncSystemPrompt ¶

func WithAsyncSystemPrompt(prompt string) AsyncSubagentsOption

WithAsyncSystemPrompt adds model instructions for the available background agents.

type AsyncSuccess ¶

type AsyncSuccess struct{ Value any }

AsyncSuccess carries a successful final value. A nil Value means the run completed without an output message; an empty string is an explicit result.

type AsyncTask ¶

type AsyncTask struct {
	TaskID        string `json:"task_id"`
	AgentName     string `json:"agent_name"`
	ThreadID      string `json:"thread_id"`
	RunID         string `json:"run_id"`
	Status        string `json:"status"`
	CreatedAt     string `json:"created_at"`
	LastCheckedAt string `json:"last_checked_at"`
	LastUpdatedAt string `json:"last_updated_at"`
}

AsyncTask is the durable provider-neutral state tracked for one background run.

type AsyncUpdateRequest ¶

type AsyncUpdateRequest struct {
	GraphID  string
	ThreadID string
	Message  string
}

AsyncUpdateRequest starts a replacement run on an existing thread.

type CompactOption ¶

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

CompactOption configures one explicit conversation compaction.

func WithCompactCutoffs ¶

func WithCompactCutoffs(cutoffs ...int) CompactOption

func WithCompactHistoryFormatter ¶

func WithCompactHistoryFormatter(format func([]damessage.Message) (string, error)) CompactOption

func WithCompactInstructions ¶

func WithCompactInstructions(instructions string) CompactOption

func WithCompactKeepMessages ¶

func WithCompactKeepMessages(count int) CompactOption

func WithCompactKeepTokens ¶

func WithCompactKeepTokens(count int) CompactOption

func WithCompactPrompt ¶

func WithCompactPrompt(prompt string) CompactOption

func WithCompactReasoning ¶

func WithCompactReasoning(reasoning damodel.Reasoning) CompactOption

func WithCompactSystemPrompt ¶

func WithCompactSystemPrompt(prompt string) CompactOption

type ContentLimit ¶

type ContentLimit struct {
	Unit   ContentLimitUnit
	Amount int
}

ContentLimit is a single token-or-byte limit. The zero value selects the documented default; Amount -1 disables the limit.

type ContentLimitUnit ¶

type ContentLimitUnit string

ContentLimitUnit selects how a content limit is measured.

const (
	ContentTokens ContentLimitUnit = "tokens"
	ContentBytes  ContentLimitUnit = "bytes"
)

type ConversationCompaction ¶

type ConversationCompaction struct {
	Summary  string
	Cutoff   int
	Older    []damessage.Message
	Recent   []damessage.Message
	Usage    *damessage.Usage
	Started  time.Time
	Finished time.Time
}

ConversationCompaction is the reusable result of one explicit compaction.

func CompactConversation ¶

func CompactConversation(ctx context.Context, model damodel.Chat, messages []damessage.Message, options ...CompactOption) (ConversationCompaction, error)

CompactConversation summarizes the portion of messages before a safe cut point and returns the recent verbatim tail. It does not mutate checkpoints or application projections.

type ConversationSubagentConversation ¶

type ConversationSubagentConversation struct {
	ConversationID string
	Slug           string
}

ConversationSubagentConversation identifies a created or reused child conversation.

type ConversationSubagentConversationRequest ¶

type ConversationSubagentConversationRequest struct {
	Slug                 string
	ParentConversationID string
	WorkingDirectory     string
}

ConversationSubagentConversationRequest identifies the child conversation to create or reuse.

type ConversationSubagentDisplay ¶

type ConversationSubagentDisplay struct {
	Slug           string `json:"slug"`
	ConversationID string `json:"conversation_id"`
}

ConversationSubagentDisplay identifies the persistent conversation created or reused by a call.

type ConversationSubagentInput ¶

type ConversationSubagentInput struct {
	Slug           string `json:"slug" description:"A short identifier for this subagent (e.g., 'research-api', 'test-runner')"`
	Prompt         string `json:"prompt" description:"The message to send to the subagent"`
	TimeoutSeconds int    `json:"timeout_seconds,omitempty"`
	Wait           *bool  `` /* 141-byte string literal not displayed */
	Model          string `json:"model,omitempty" description:"LLM model for the subagent. Defaults to the parent conversation's model."`
	Reasoning      string `` /* 167-byte string literal not displayed */
}

ConversationSubagentInput is the input accepted by ConversationSubagentTool.

type ConversationSubagentModel ¶

type ConversationSubagentModel struct {
	ID          string
	DisplayName string
}

ConversationSubagentModel describes a model exposed to child conversations.

type ConversationSubagentOptions ¶

type ConversationSubagentOptions struct {
	AvailableModels []ConversationSubagentModel
	ParentReasoning string
	ReasoningLevels []string
	DefaultTimeout  time.Duration
	MaxTimeout      time.Duration
}

ConversationSubagentOptions configures a persistent conversation subagent tool.

type ConversationSubagentReply ¶

type ConversationSubagentReply struct {
	Content string
}

ConversationSubagentReply is the visible response from a child conversation.

type ConversationSubagentRun ¶

type ConversationSubagentRun struct {
	ConversationID string
	Prompt         string
	Wait           bool
	Timeout        time.Duration
	ModelID        string
	Reasoning      string
}

ConversationSubagentRun describes one turn in a persistent child conversation.

type ConversationSubagentRunner ¶

type ConversationSubagentRunner interface {
	RunSubagent(context.Context, ConversationSubagentRun) (ConversationSubagentReply, error)
}

ConversationSubagentRunner executes a turn in a persistent child conversation.

type ConversationSubagentStore ¶

type ConversationSubagentStore interface {
	GetOrCreateSubagentConversation(context.Context, ConversationSubagentConversationRequest) (ConversationSubagentConversation, error)
}

ConversationSubagentStore resolves a stable child conversation from its slug.

type Filesystem ¶

type Filesystem struct {
	Permissions      []FilesystemPermission
	Tools            []string
	ToolDescriptions map[string]string
	ReadLimit        int
	GrepLimit        int
	// GrepUncapped disables the configured default match cap. Individual grep
	// calls can also request this behavior with an explicit JSON null max_count.
	GrepUncapped      bool
	GlobTimeout       time.Duration
	MaxExecuteTimeout time.Duration
	ToolResultLimit   ContentLimit
	// HumanMessageTokenLimit uses zero for its documented default and -1 to
	// disable the limit. Positive values select an explicit token limit.
	HumanMessageTokenLimit  int
	ArtifactsRoot           string
	ConversationHistoryRoot string
	VideoExtractor          davideo.Extractor
	MaxVideoBytes           int
	VideoSamplingRate       float64
	// contains filtered or unexported fields
}

Filesystem configures the agent-owned filesystem facility. New binds it to the agent's Backend and compiles the corresponding middleware.

type FilesystemOperation ¶

type FilesystemOperation string
const (
	FilesystemRead  FilesystemOperation = "read"
	FilesystemWrite FilesystemOperation = "write"
)

type FilesystemPermission ¶

type FilesystemPermission struct {
	Operations []FilesystemOperation
	Paths      []string
	Mode       PermissionMode
}

FilesystemPermission is evaluated in declaration order; the first matching rule wins. Unmatched operations are allowed.

type GeneralPurposeSubagentMode ¶

type GeneralPurposeSubagentMode string
const (
	GeneralPurposeSubagentEnabled  GeneralPurposeSubagentMode = "enabled"
	GeneralPurposeSubagentDisabled GeneralPurposeSubagentMode = "disabled"
)

type GeneralPurposeSubagentProfile ¶

type GeneralPurposeSubagentProfile struct {
	Mode         GeneralPurposeSubagentMode
	Description  *string
	SystemPrompt *string
}

GeneralPurposeSubagentProfile controls the automatically added worker. An empty Mode inherits; otherwise it explicitly enables or disables the worker.

type HarnessProfilePlugin ¶

type HarnessProfilePlugin struct {
	Name     string
	Register func() error
}

HarnessProfilePlugin identifies an explicitly imported harness-profile plugin. Register may call RegisterHarnessProfile one or more times.

Go does not provide a portable equivalent of Python package entry points, so applications must import plugin packages and pass their registration functions to LoadHarnessProfilePlugins (or rely on an imported package's init function calling RegisterHarnessProfile).

type Interpreter ¶

type Interpreter struct {
	ToolName         string
	Timeout          time.Duration
	MemoryLimit      uint64
	StackLimit       uint64
	MaxStdoutChars   int
	MaxResultChars   int
	MaxSnapshotBytes int
	MaxPTCCalls      int
	// PTC is an allowlist of agent tool names exposed as async functions under
	// tools.*. Nil selects the read-only filesystem tools; an empty non-nil
	// slice disables programmatic tool calling.
	PTC []string
	// PTCTransparency emits programmatic tool calls through the ordinary tool
	// lifecycle stream so user interfaces and protocol adapters can render
	// them like model-originated calls. It does not add the calls to model
	// history or route them through tool-call middleware.
	PTCTransparency bool
}

Interpreter configures the agent-owned JavaScript code interpreter. Normal Go builds host an isolated QuickJS-ng WASM instance in Wazero. TinyGo builds exclude that implementation and reject interpreter configurations.

type Memory ¶

type Memory struct {
	Sources []string
	// Contents supplies already-loaded source text. Entries whose paths appear
	// in Sources are used without downloading them from Backend.
	Contents     map[string]string
	SystemPrompt PromptTemplate
	// ReadOnly selects the default prompt that exposes memory as reference
	// material without asking the model to persist new learnings. An explicit
	// SystemPrompt still takes precedence.
	ReadOnly bool
}

Memory configures the agent-owned memory facility. New binds it to the agent's Backend and compiles the corresponding middleware.

type Option ¶

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

Option configures an agent constructed by New.

func WithApprovalRules ¶

func WithApprovalRules(rules ...dagent.ApprovalRule) Option

WithApprovalRules adds human-approval middleware.

func WithAsyncSubagents ¶

func WithAsyncSubagents(subagents []AsyncSubagent, options ...AsyncSubagentsOption) Option

WithAsyncSubagents adds hosted asynchronous-subagent middleware.

func WithBackend ¶

func WithBackend(backend dabackend.Backend) Option

WithBackend sets the backend used by backend-backed middleware.

func WithCache ¶

func WithCache(cache dacache.Cache) Option

WithCache sets the runtime cache.

func WithDebug ¶

func WithDebug() Option

WithDebug enables graph debug logging.

func WithDependencies ¶

func WithDependencies(dependencies any) Option

WithDependencies sets construction-time runtime dependencies.

func WithFatalToolErrors ¶

func WithFatalToolErrors() Option

WithFatalToolErrors makes operational tool failures terminate the invocation.

func WithFilesystem ¶

func WithFilesystem(filesystem Filesystem) Option

WithFilesystem adds filesystem middleware with the given configuration.

func WithInterpreter ¶

func WithInterpreter(interpreter Interpreter) Option

WithInterpreter adds persistent JavaScript interpreter middleware.

func WithLogger ¶

func WithLogger(logger *slog.Logger) Option

WithLogger routes enabled graph debug events to logger. An omitted logger preserves slog.Default behavior; a nil explicit logger is a static error.

func WithMaxConcurrency ¶

func WithMaxConcurrency(limit int) Option

WithMaxConcurrency sets the maximum concurrent graph tasks.

func WithMemory ¶

func WithMemory(memory Memory) Option

WithMemory adds persistent-memory prompt middleware.

func WithMetadata ¶

func WithMetadata(metadata map[string]json.RawMessage) Option

WithMetadata sets invocation metadata used by tracing and evaluation adapters.

func WithMiddleware ¶

func WithMiddleware(middleware ...dagent.Middleware) Option

WithMiddleware appends caller-provided middleware. A later middleware with the same name replaces the earlier contribution.

func WithName ¶

func WithName(name string) Option

WithName sets the name stamped on model responses.

func WithProfiles ¶

func WithProfiles(profiles ...Profile) Option

WithProfiles sets the ordered harness profiles applied to the agent.

func WithPromptCache ¶

func WithPromptCache(options PromptCacheOptions) Option

WithPromptCache enables current prompt-cache options. It panics when static values cannot be accepted by the provider API.

func WithPromptCacheRetention ¶

func WithPromptCacheRetention(retention string) Option

WithPromptCacheRetention adds provider prompt-caching middleware.

func WithRecursionLimit ¶

func WithRecursionLimit(limit int) Option

WithRecursionLimit sets the maximum graph steps for one invocation.

func WithRetainedThreadState ¶

func WithRetainedThreadState() Option

WithRetainedThreadState keeps active thread state in memory between invocations.

func WithSaver ¶

func WithSaver(saver dacheckpoint.Saver) Option

WithSaver sets the thread checkpoint saver.

func WithSkills ¶

func WithSkills(skills Skills) Option

WithSkills adds skill-discovery middleware.

func WithStateFields ¶

func WithStateFields(fields map[string]dagent.StateField) Option

WithStateFields sets application-owned state fields and reducers.

func WithStore ¶

func WithStore(store dastore.Store) Option

WithStore sets the durable cross-thread store.

func WithStructuredOutput ¶

func WithStructuredOutput(output *dagent.StructuredOutput) Option

WithStructuredOutput sets the agent's structured response contract.

func WithSubagents ¶

func WithSubagents(subagents ...Subagent) Option

WithSubagents adds task delegation middleware. Calling it without explicit subagents enables only the default general-purpose worker.

func WithSummarization ¶

func WithSummarization(summarization Summarization) Option

WithSummarization adds automatic conversation-summarization middleware.

func WithSystemMessage ¶

func WithSystemMessage(message damessage.Message) Option

WithSystemMessage sets the agent's system message.

func WithSystemPrompt ¶

func WithSystemPrompt(prompt string) Option

WithSystemPrompt sets a plain-text system message.

func WithTags ¶

func WithTags(tags ...string) Option

WithTags sets invocation tags used by tracing and evaluation adapters.

func WithTodo ¶

func WithTodo(options ...dagent.TodoOption) Option

WithTodo adds todo-list middleware.

func WithTools ¶

func WithTools(tools ...datool.Tool) Option

WithTools sets the caller-provided model tools.

func WithoutMiddleware ¶

func WithoutMiddleware(names ...string) Option

WithoutMiddleware removes inherited or profile-provided middleware by public or serialized name. It is primarily useful for declarative child agents.

type PermissionMode ¶

type PermissionMode string
const (
	PermissionAllow     PermissionMode = "allow"
	PermissionDeny      PermissionMode = "deny"
	PermissionInterrupt PermissionMode = "interrupt"
)

type Profile ¶

type Profile struct {
	Name               string
	BaseSystemPrompt   *string
	SystemPromptSuffix *string
	SystemPrompt       string
	ToolDescriptions   map[string]string
	ExcludeTools       []string
	Middleware         []dagent.Middleware
	ExcludeMiddleware  []string
	GeneralPurpose     *GeneralPurposeSubagentProfile
}

Profile is a composable construction overlay. Later profiles win for scalar and tool-description values; slices append in declaration order.

func MergeProfiles ¶

func MergeProfiles(profiles ...Profile) Profile

type PromptCacheOptions ¶

type PromptCacheOptions struct {
	Key string
}

PromptCacheOptions configures prompt caching for current OpenAI models. Key may be omitted to derive a stable routing key from the agent's prompt shape.

type PromptMode ¶

type PromptMode string
const (
	PromptCustom   PromptMode = "custom"
	PromptDisabled PromptMode = "disabled"
)

type PromptTemplate ¶

type PromptTemplate struct {
	Mode PromptMode
	Text string
}

PromptTemplate represents the default, a custom template, or no prompt without pointer-to-scalar option fields.

type RubricCriterionEvaluation ¶

type RubricCriterionEvaluation struct {
	Name   string `json:"name"`
	Passed bool   `json:"passed"`
	Gap    string `json:"gap,omitempty"`
}

type RubricEvaluation ¶

type RubricEvaluation struct {
	GradingRunID string                      `json:"grading_run_id"`
	Iteration    int                         `json:"iteration"`
	Result       RubricResult                `json:"result"`
	Explanation  string                      `json:"explanation"`
	Criteria     []RubricCriterionEvaluation `json:"criteria"`
}

type RubricGraderResponse ¶

type RubricGraderResponse struct {
	Result      RubricResult                `json:"result"`
	Explanation string                      `json:"explanation"`
	Criteria    []RubricCriterionEvaluation `json:"criteria"`
}

type RubricOptions ¶

type RubricOptions struct {
	SystemPrompt      string
	Tools             []datool.Tool
	MaxIterations     int
	MaxIterationsFunc func() int
	OnEvaluation      func(RubricEvaluation)
}

type RubricResult ¶

type RubricResult string
const (
	RubricSatisfied     RubricResult = "satisfied"
	RubricNeedsRevision RubricResult = "needs_revision"
	RubricFailed        RubricResult = "failed"
	RubricMaxIterations RubricResult = "max_iterations_reached"
	RubricGraderError   RubricResult = "grader_error"
)

type RubricSnapshot ¶

type RubricSnapshot struct {
	Criteria    string             `json:"criteria,omitempty"`
	Status      RubricResult       `json:"status,omitempty"`
	Iterations  int                `json:"iterations"`
	Evaluations []RubricEvaluation `json:"evaluations,omitempty"`
}

RubricSnapshot is the durable, host-facing view of rubric state. Criteria and the latest verdict are public because hosts need them to restore their controls; grading bookkeeping remains private to the middleware.

func RubricSnapshotFromState ¶

func RubricSnapshotFromState(values dastate.Values) RubricSnapshot

RubricSnapshotFromState projects live or checkpoint-restored agent state into a detached host view. Malformed fields fail closed to their zero values instead of leaking loosely typed checkpoint data to callers.

type Runnable ¶

type Runnable interface {
	Invoke(context.Context, ...dagent.RunOption) (dagent.Result, error)
}

Runnable is the small invocation contract accepted by compiled subagents.

type RunnableSubagentOption ¶

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

RunnableSubagentOption configures delegation to an already compiled runnable. Agent construction options are intentionally unavailable because the graph has already been built.

func WithInheritedState ¶

func WithInheritedState(keys ...string) RunnableSubagentOption

WithInheritedState selects parent state fields copied into an already compiled runnable subagent and propagated back when changed.

type Skill ¶

type Skill = skillpkg.Skill

type SkillSource ¶

type SkillSource struct {
	Path  string
	Label string
}

type Skills ¶

type Skills struct {
	Sources        []string
	LabeledSources []SkillSource
	// Catalog supplies skills that were discovered by an application. Filesystem
	// sources remain higher priority and replace catalog entries with the same
	// name.
	Catalog []Skill
	// Activate returns the progressive-disclosure instruction for a skill. The
	// default uses a catalog skill's Body, then falls back to telling the agent
	// to read the skill file through the filesystem tools.
	Activate     func(Skill) string
	SystemPrompt PromptTemplate
	MaxFileBytes int
	Warn         func(string)
}

Skills configures the agent-owned skill catalog. New binds it to the agent's Backend and compiles the corresponding middleware.

type StreamingRunnable ¶

type StreamingRunnable interface {
	Runnable
	Stream(context.Context, ...dagent.RunOption) *dagent.Stream
}

StreamingRunnable lets a compiled subagent project its nested lifecycle onto the parent stream. Runnable remains sufficient for invoke-only integrations.

type Subagent ¶

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

func NewRunnableSubagent ¶

func NewRunnableSubagent(name, description string, runnable Runnable, options ...RunnableSubagentOption) Subagent

NewRunnableSubagent registers an already compiled runnable. It accepts only delegation options because agent construction options cannot reconfigure a compiled graph.

func NewSubagent ¶

func NewSubagent(name, description string, model damodel.Chat, options ...Option) Subagent

NewSubagent declares an agent compiled with the same functional options as a top-level agent. A nil model inherits the parent model.

func (Subagent) WithInheritedState ¶

func (subagent Subagent) WithInheritedState(keys ...string) Subagent

WithInheritedState selects parent state fields copied into this declarative subagent and propagated back when changed. Calling it with no keys disables inheritance. It is separate from Option because delegation is not part of agent construction.

type SubagentsOption ¶

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

SubagentsOption configures one subagent middleware construction.

func WithPrivateState ¶

func WithPrivateState(keys ...string) SubagentsOption

WithPrivateState prevents selected parent state fields from reaching child agents.

type Summarization ¶

type Summarization struct {
	// Model overrides the agent model for summary generation. Nil reuses the
	// agent model.
	Model damodel.Chat
	// TriggerClauses are ORed together; every non-zero threshold within one
	// clause must match. This represents Deep Agents' list-of-trigger-clauses
	// contract without Python tuple/dict unions.
	TriggerClauses       []SummarizationTriggerClause
	KeepMessages         int
	KeepTokens           int
	KeepFraction         float64
	HistoryRoot          string
	MediaRoot            string
	OverflowClipTokens   int
	LargeToolResultsRoot string
	SummaryPrompt        string
	// Nil selects profile-aware defaults. An empty value disables argument
	// truncation; a populated value supplies a custom policy.
	ArgumentTruncation *ArgumentTruncationOptions
}

Summarization configures the agent-owned conversation compactor. New binds its model and backend and compiles the corresponding middleware.

type SummarizationToolOptions ¶

type SummarizationToolOptions struct {
	Summarization Summarization
	// SystemPrompt optionally nudges the model to use compact_conversation.
	SystemPrompt string
}

type SummarizationTriggerClause ¶

type SummarizationTriggerClause struct {
	Tokens   int
	Messages int
	Fraction float64
}

Directories ¶

Path Synopsis
Package browser contains reusable building blocks for agents that run as Go WebAssembly inside a browser worker.
Package browser contains reusable building blocks for agents that run as Go WebAssembly inside a browser worker.
browserfs
Package browserfs implements a bounded, just-in-time browser workspace for Go WebAssembly agents.
Package browserfs implements a bounded, just-in-time browser workspace for Go WebAssembly agents.
checkpoint
Package checkpoint implements browser persistence for graph checkpoints.
Package checkpoint implements browser persistence for graph checkpoints.
jsbridge
Package jsbridge contains syscall/js helpers for exposing asynchronous Go functions to browser JavaScript and awaiting JavaScript promises.
Package jsbridge contains syscall/js helpers for exposing asynchronous Go functions to browser JavaScript and awaiting JavaScript promises.
justbash
Package justbash defines the portable request boundary used to run a sandboxed just-bash shell beside a Go WebAssembly agent.
Package justbash defines the portable request boundary used to run a sandboxed just-bash shell beside a Go WebAssembly agent.
webgpu
Package webgpu adapts an asynchronous browser inference function to the damodel.Chat interface for Go WebAssembly agents.
Package webgpu adapts an asynchronous browser inference function to the damodel.Chat interface for Go WebAssembly agents.
cmd
dacode command
dago command
datalon command
Command datalon exposes local long-running assistant utilities.
Command datalon exposes local long-running assistant utilities.
Package daacp exposes dago agents through Agent Client Protocol version 1.
Package daacp exposes dago agents through Agent Client Protocol version 1.
Package daagentprotocol adapts the Agent Protocol HTTP API to background subagents.
Package daagentprotocol adapts the Agent Protocol HTTP API to background subagents.
Package daaskuser provides an opt-in tool for asking structured questions during an agent run.
Package daaskuser provides an opt-in tool for asking structured questions during an agent run.
Package dabackend defines virtual file and optional shell capabilities used by deep agent filesystem middleware.
Package dabackend defines virtual file and optional shell capabilities used by deep agent filesystem middleware.
agentcore
Package agentcore adapts a caller-authenticated AgentCore Code Interpreter transport to dago's sandbox contracts.
Package agentcore adapts a caller-authenticated AgentCore Code Interpreter transport to dago's sandbox contracts.
contexthub
Package contexthub stores a dago virtual file tree in a persistent Context Hub agent repository.
Package contexthub stores a dago virtual file tree in a persistent Context Hub agent repository.
daytona
Package daytona adapts caller-supplied Daytona transports to dago's sandbox backend.
Package daytona adapts caller-supplied Daytona transports to dago's sandbox backend.
docker
Package docker provides an explicitly constructed sandbox backed by a local Docker Engine.
Package docker provides an explicitly constructed sandbox backed by a local Docker Engine.
langsmith
Package langsmith adapts a LangSmith remote sandbox to dago's backend contracts.
Package langsmith adapts a LangSmith remote sandbox to dago's backend contracts.
modal
Package modal adapts a caller-supplied Modal sandbox transport to dago's sandbox backend.
Package modal adapts a caller-supplied Modal sandbox transport to dago's sandbox backend.
runloop
Package runloop adapts caller-supplied Runloop devbox transports to dago's sandbox backend.
Package runloop adapts caller-supplied Runloop devbox transports to dago's sandbox backend.
vercel
Package vercel adapts a caller-supplied Vercel Sandbox transport to dago's sandbox backend.
Package vercel adapts a caller-supplied Vercel Sandbox transport to dago's sandbox backend.
Package dacache defines deterministic node and model result caching contracts.
Package dacache defines deterministic node and model result caching contracts.
Package dacheckpoint defines durable graph execution records and saver contracts.
Package dacheckpoint defines durable graph execution records and saver contracts.
postgres
Package postgres implements the standard Python-schema-compatible PostgreSQL saver.
Package postgres implements the standard Python-schema-compatible PostgreSQL saver.
serde
Package serde implements the safe language-neutral checkpoint payload subset.
Package serde implements the safe language-neutral checkpoint payload subset.
sqlite
Package sqlite implements the standard Python-schema-compatible SQLite saver.
Package sqlite implements the standard Python-schema-compatible SQLite saver.
Package daconfig provides provider-neutral layered configuration contracts.
Package daconfig provides provider-neutral layered configuration contracts.
Package dacost provides provider-neutral, bounded token and cost accounting.
Package dacost provides provider-neutral, bounded token and cost accounting.
Package dacredential stores provider and service credentials in an owner-private, versioned file without owning provider SDKs or login flows.
Package dacredential stores provider and service credentials in an owner-private, versioned file without owning provider SDKs or login flows.
Package dadoctor collects bounded, offline diagnostics suitable for pasting into support reports.
Package dadoctor collects bounded, offline diagnostics suitable for pasting into support reports.
Package daenv resolves bounded project and user dotenv layers without mutating the process environment.
Package daenv resolves bounded project and user dotenv layers without mutating the process environment.
Package daeval evaluates agent behavior from provider-neutral trajectories.
Package daeval evaluates agent behavior from provider-neutral trajectories.
clbench
Package clbench adapts a caller-supplied structured agent to the continual-learning-bench system lifecycle.
Package clbench adapts a caller-supplied structured agent to the continual-learning-bench system lifecycle.
harbor
Package harbor runs sandboxed benchmarks through caller-supplied transports.
Package harbor runs sandboxed benchmarks through caller-supplied transports.
scorecard
Package scorecard compares provider-neutral evaluation results across models.
Package scorecard compares provider-neutral evaluation results across models.
Package daeventbus provides opt-in, transport-neutral external event ingress.
Package daeventbus provides opt-in, transport-neutral external event ingress.
Package dagent implements the provider-neutral model/tool loop and middleware contracts required by deep agents.
Package dagent implements the provider-neutral model/tool loop and middleware contracts required by deep agents.
Package dagit reads lightweight Git repository metadata without requiring a Git subprocess for ordinary repository layouts.
Package dagit reads lightweight Git repository metadata without requiring a Git subprocess for ordinary repository layouts.
Package dagoal provides durable, provider-neutral goals for dago agents.
Package dagoal provides durable, provider-neutral goals for dago agents.
Package dahook implements the versioned lifecycle-hook protocol used by dago hosts.
Package dahook implements the versioned lifecycle-hook protocol used by dago hosts.
Package dahousekeeping provides bounded, application-owned startup chores.
Package dahousekeeping provides bounded, application-owned startup chores.
Package dainstall provides a closed-catalog dependency installer.
Package dainstall provides a closed-catalog dependency installer.
Package damanaged provides a bounded client for the managed-agent API.
Package damanaged provides a bounded client for the managed-agent API.
Package damcp implements host-neutral policy for project-supplied MCP servers.
Package damcp implements host-neutral policy for project-supplied MCP servers.
Package damessage defines the provider-neutral messages exchanged by models, tools, agents, and checkpoints.
Package damessage defines the provider-neutral messages exchanged by models, tools, agents, and checkpoints.
Package damodel defines provider-neutral chat model contracts.
Package damodel defines provider-neutral chat model contracts.
modeltest
Package modeltest provides deterministic model doubles for tests and examples.
Package modeltest provides deterministic model doubles for tests and examples.
Package daplugin provides bounded local plugin and marketplace management.
Package daplugin provides bounded local plugin and marketplace management.
Package daprofilecfg provides safe JSON and YAML harness-profile configuration.
Package daprofilecfg provides safe JSON and YAML harness-profile configuration.
daproviders
anthropic
Package anthropic adapts Anthropic's Messages API to damodel.Chat.
Package anthropic adapts Anthropic's Messages API to damodel.Chat.
claudeagent
Package claudeagent adapts the Claude CLI print protocol to damodel.Chat.
Package claudeagent adapts the Claude CLI print protocol to damodel.Chat.
langsmithgateway
Package langsmithgateway resolves provider:model specifications through the LangSmith LLM Gateway without owning provider SDKs or credentials discovery.
Package langsmithgateway resolves provider:model specifications through the LangSmith LLM Gateway without owning provider SDKs or credentials discovery.
modelconfig
Package modelconfig resolves provider-qualified and bare model names into caller-owned model factories.
Package modelconfig resolves provider-qualified and bare model names into caller-owned model factories.
nemotron
Package nemotron provides harness profiles and middleware for NVIDIA Nemotron models.
Package nemotron provides harness profiles and middleware for NVIDIA Nemotron models.
ollama
Package ollama discovers models exposed by an explicitly selected local Ollama daemon.
Package ollama discovers models exposed by an explicitly selected local Ollama daemon.
openai
Package openai adapts the OpenAI Responses API to dago's provider-neutral model contract.
Package openai adapts the OpenAI Responses API to dago's provider-neutral model contract.
openrouter
Package openrouter adapts OpenRouter's OpenAI-compatible Responses API to dago's provider-neutral model contract.
Package openrouter adapts OpenRouter's OpenAI-compatible Responses API to dago's provider-neutral model contract.
profile
Package profile applies explicit provider-construction profiles.
Package profile applies explicit provider-construction profiles.
Package darepository provides bounded, read-only repository tools for untrusted nested agents such as acceptance-criteria drafters and graders.
Package darepository provides bounded, read-only repository tools for untrusted nested agents such as acceptance-criteria drafters and graders.
Package dasandbox resolves and owns remote sandbox sessions across built-in, extension, and application-configured provider factories.
Package dasandbox resolves and owns remote sandbox sessions across built-in, extension, and application-configured provider factories.
Package daserver exposes dago agents through the LangGraph Agent Server HTTP protocol used by LangSmith Studio and the LangGraph SDKs.
Package daserver exposes dago agents through the LangGraph Agent Server HTTP protocol used by LangSmith Studio and the LangGraph SDKs.
Package daskill implements the language-neutral Agent Skills metadata contract.
Package daskill implements the language-neutral Agent Skills metadata contract.
Package dastate defines language-neutral graph state values and update markers.
Package dastate defines language-neutral graph state values and update markers.
Package dastore defines namespaced durable memory used by graph and agent runs.
Package dastore defines namespaced durable memory used by graph and agent runs.
sqlite
Package sqlite provides a durable namespaced store with versioned migrations.
Package sqlite provides a durable namespaced store with versioned migrations.
Package dasubagent discovers declarative subagent definitions from bounded, confined AGENTS.md files.
Package dasubagent discovers declarative subagent definitions from bounded, confined AGENTS.md files.
Package datalon provides an experimental local host for long-running agents.
Package datalon provides an experimental local host for long-running agents.
approval
Package approval provides Talon's experimental channel tool-approval policy.
Package approval provides Talon's experimental channel tool-approval policy.
cron
Package cron provides persistent minute-granularity jobs for datalon hosts.
Package cron provides persistent minute-granularity jobs for datalon hosts.
fleet
Package fleet imports Fleet zip exports into a local datalon assistant state directory.
Package fleet imports Fleet zip exports into a local datalon assistant state directory.
lifecycle
Package lifecycle applies bounded retention policy to one datalon assistant's sensitive local state.
Package lifecycle applies bounded retention policy to one datalon assistant's sensitive local state.
mcp
Package mcp loads Model Context Protocol tools for a long-running assistant.
Package mcp loads Model Context Protocol tools for a long-running assistant.
mcp/oauthpolicy
Package oauthpolicy selects bounded, provider-specific OAuth policies for remote MCP servers.
Package oauthpolicy selects bounded, provider-specific OAuth policies for remote MCP servers.
speech
Package speech provides opt-in inbound voice transcription for datalon channels.
Package speech provides opt-in inbound voice transcription for datalon channels.
telegram
Package telegram adapts Telegram's Bot API to datalon.Channel.
Package telegram adapts Telegram's Bot API to datalon.Channel.
tracing
Package tracing adds provider-neutral per-run tracing to a datalon runtime.
Package tracing adds provider-neutral per-run tracing to a datalon runtime.
tracing/langsmith
Package langsmith adapts LangSmith run ingestion to datalon tracing.
Package langsmith adapts LangSmith run ingestion to datalon tracing.
whatsapp
Package whatsapp adapts datalon to the packaged loopback WhatsApp Node bridge.
Package whatsapp adapts datalon to the packaged loopback WhatsApp Node bridge.
Package datool defines provider-neutral tool schemas and execution contracts.
Package datool defines provider-neutral tool schemas and execution contracts.
Package daupdate verifies and atomically activates signed release artifacts.
Package daupdate verifies and atomically activates signed release artifacts.
Package davideo defines video extraction contracts and an optional FFmpeg adapter.
Package davideo defines video extraction contracts and an optional FFmpeg adapter.
Package daweb provides opt-in HTTP, page-fetching, and Tavily search tools.
Package daweb provides opt-in HTTP, page-fetching, and Tavily search tools.
Package daworkflow provides deterministic JavaScript orchestration as an optional dago middleware extension.
Package daworkflow provides deterministic JavaScript orchestration as an optional dago middleware extension.
Package daworkspace discovers workspace instructions and conventional local configuration shared by dago applications.
Package daworkspace discovers workspace instructions and conventional local configuration shared by dago applications.
examples
basic command
openai command
studio
Package studio provides a network-free agent for exercising dago with LangSmith Studio.
Package studio provides a network-free agent for exercising dago with LangSmith Studio.
internal
dacli
Package dacli contains shared command-line workflows for the dago binary.
Package dacli contains shared command-line workflows for the dago binary.
optionvalue
Package optionvalue resolves optional zero-or-one configuration values.
Package optionvalue resolves optional zero-or-one configuration values.
quickjswasm
Package quickjswasm embeds the QuickJS-ng execution guest shipped by quickjs-rs v0.2.5 and dago's source-controlled fork of its transform guest.
Package quickjswasm embeds the QuickJS-ng execution guest shipped by quickjs-rs v0.2.5 and dago's source-controlled fork of its transform guest.
unicodesecurity
Package unicodesecurity detects text and URLs that may render deceptively.
Package unicodesecurity detects text and URLs that may render deceptively.
wafl
Package wafl instruments WebAssembly stores with passive page-dirty tracking.
Package wafl instruments WebAssembly stores with passive page-dirty tracking.

Jump to

Keyboard shortcuts

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