Threads AI

dynamicAgent / dynamic_agent

Describe a dynamic agent: a template in a lead's team whose members the lead (or team.start) defines at runtime within what this code pins.

A start may choose only a label, instructions (added last, in a delimited block), a subset of this template's tools (built-ins included; the framework tools are always kept) and a models key; everything else (permissions, hooks, skills, memory, sandbox, budget, output) is this config. Only a team lists it: in subagents or handoffs it is ConfigError invalid_config. The lead's instructions list its choosable tools and model keys, so renaming a tool or a key changes the lead's pinned config and an existing lead thread no longer continues. Tools of its MCP servers are choosable but not listed, since the listing never waits on a connection. Pure, like agent().

Import from @threads/core (TypeScript) or threads (Python).

function dynamicAgent(options: {
  models: Record<string, Model>;
  instructions?: string;
  name?: Name;
  tools?: readonly (Tool | McpServer)[];
  extensions?: readonly Extension[];
  sandbox?: Sandbox;
  memory?: MemoryProvider;
  memoryWrite?: "deny" | "ask" | "allow_principal" | "allow";
  knowledge?: KnowledgeProvider;
  skills?: readonly Skill[];
  output?: z.ZodType<Output>;
  outputRetries?: number;
  fallback?: readonly Model[];
  permissions?: Partial<Policy.permissions>;
  approvers?: readonly Principal[];
  budget?: Budget;
  onUnknownUsage?: Policy.on_unknown_usage;
  retry?: Partial<Policy.retry>;
  context?: Partial<Policy.context>;
  egress?: readonly string[] | "unenforced";
  web?: { fetch?: boolean; search?: SearchBackend };
  git?: { credential: Secret; forgeUrl?: string; apiUrl?: string };
  computer?: boolean;
  lsp?: { languages: readonly string[] };
  outputStyles?: Record<string, string>;
}): DynamicAgent<Deps, Output>

Parameters

modelsRecord<string, Model>required

The models a starter may choose from, by key, in order: the first key is the default. Non-empty, each key a name (lowercase letters, digits and underscores, starting with a letter), else ConfigError invalid_config. A start's model field names a key; the member runs that model.

instructionsstring

The fixed preamble every member of this template starts its the system prompt with. A starter's written instructions follow it and everything else, in a delimited block that comes last. Omitted: none.

nameNamedefault agent

The template's name: the agent a start names, and each member is <name>-<k>. Unique in the team tree; operator is reserved.

toolsreadonly (Tool | McpServer)[]default []

App tools and MCP servers. Built-in tools come from the sandbox and the options below.

extensionsreadonly Extension[]default []

Instructions and hooks run in this order.

sandboxSandbox

The sandbox the sandbox tools run in: bash and the file tools (read, write, edit, ls, glob, grep). The git, lsp and computer options also need one. Omitted: no sandbox tools. See Sandbox.

memoryMemoryProvider

Saved cross-run memory: localMemory() or a memory adapter. It pins save_memory, search_memory and forget_memory. Omitted: the agent has no memory tools. See MemoryProvider.

memoryWrite / memory_write"deny" | "ask" | "allow_principal" | "allow"default ask

Write authority for save_memory.

knowledgeKnowledgeProvider

Retrieval over sources the host admits: localKnowledge(paths) or a knowledge adapter. It pins search_knowledge. Omitted: the agent has no knowledge tool. See KnowledgeProvider.

skillsreadonly Skill[]default []

Pinned in config_hash (name, description, sha256 of body). The system prompt lists them after the extension instructions as "Skills you can load with load_skill:" then one "- name: description" line each, in the given order; load_skill (pinned only when this is non-empty) appends the body as injected{source: skill, trust: trusted_instruction, origin: {id: name, version: sha256 of body}}. Unique names; a description is one non-empty line.

outputz.ZodType<Output>

Structured final output: a schema the final answer must parse with. Omitted: completed.output is the final text.

outputRetries / output_retriesnumberdefault 2

Failed candidates per turn (a rejected final_output or a plain-text end) before turn_completed{output_invalid}. An integer from 0 to 2^53-1; anything else is ConfigError invalid_config.

fallbackreadonly Model[]default []

Fallback models in order. With the default fallback_scope turn, the next user_input reverts to the settings before the fallback (settings_changed{reason: revert}), gated by before_model_switch.

permissionsPartial<Policy.permissions>

The permission policy every tool call is decided under: mode, allow, ask and deny rules, protected_paths, allow_bypass and plan_exit_mode. In TypeScript the fields you give override the defaults; Python takes a complete Permissions. Omitted: mode default, no rules, the built-in protected paths, allow_bypass false and plan_exit_mode default.

approversreadonly Principal[]

Who may answer approval challenges and resolve parked effects for runs this agent roots, its subagents and handoff targets included. Omitted: only the root run's originating principal (the principal of the root thread's latest user_input).

budgetBudget

Thread budget: limits such as max_turns, max_model_requests, max_input_tokens, max_output_tokens, max_cost_nanos and max_wall_ms, checked before every model request. It covers the thread and every descendant. Omitted: no thread budget.

onUnknownUsage / on_unknown_usagePolicy.on_unknown_usagedefault upper_bound

How a budget counts a model attempt the provider reports no usage for. upper_bound counts it at its conservative upper bound; stop lets a limit the model can't bound per attempt pass setup and refuses it at run time instead of failing setup with budget_unenforceable.

retryPartial<Policy.retry>

Model retry settings: max_retries, base_delay_ms, max_delay_ms, max_retry_after_ms, max_total_wait_ms, crash_resends, fallback_after, fallback_scope and heartbeat_ms. In TypeScript the fields you give override the defaults; Python takes a complete Retry. Omitted: the default policy (8 retries, 1000 ms base delay doubling up to 32000 ms, fallback after 3 failures in a turn).

contextPartial<Policy.context>

Context-window settings: reserve_tokens, clearing old tool results, spilling large results, compaction and what is restored after it, output continuations and tool deferral. In TypeScript the fields you give override the defaults; Python takes a complete Context. Omitted: the default context policy, with cache_ttl_ms from the models' declared cache lifetimes (ModelInfo.cache) when they agree; models that disagree, or whose lifetime is unknown, need cache_ttl_ms set (checked at check() or the first run).

egressreadonly string[] | "unenforced"default []

Sandbox egress allowlist of hosts. [] is deny-all. unenforced opts in to a provider that can't enforce it; stub mode then refuses.

web{ fetch?: boolean; search?: SearchBackend }

Host-side web tools: web_fetch and web_search run on the host, not in the sandbox. Omitted: no web tools.

web.fetchbooleandefault false

true pins web_fetch, which fetches a URL from the host. false (the default) leaves it out.

web.searchSearchBackend

The search backend web_search uses (an adapter such as exa, brave or tavily). Omitted: no web_search tool.

git{ credential: Secret; forgeUrl?: string; apiUrl?: string }

Enables the git gateway tools git_clone, git_fetch, git_push and open_pull_request. The forge is GitHub; the credential is revealed only on the host and never enters the sandbox. Needs a sandbox. Omitted: no git tools.

git.credentialSecretrequired

The forge token, as a secret(). It is revealed only on the host when a git tool talks to the forge, never in the sandbox.

git.forgeUrl / git.forge_urlstringdefault https://github.com

A repo owner/name lives at <forge_url>/<owner>/<name>.git.

git.apiUrl / git.api_urlstringdefault https://api.github.com

The forge REST API open_pull_request uses.

computerbooleandefault false

Pins computer_screenshot (read_only) and computer (actions, unguarded). Needs a sandbox whose info.desktop is native or image; otherwise a setup error capability_missing.

lsp{ languages: readonly string[] }

Pins lsp for these languages (typescript, python, go, rust), run in the sandbox image's language servers. Needs a sandbox; an unknown language is unknown_preset. A server that isn't installed or ready answers unavailable at run time. Omitted: no lsp tool.

lsp.languagesreadonly string[]required

The languages lsp serves: typescript, python, go or rust. Any other name is a setup error unknown_preset.

outputStyles / output_stylesRecord<string, string>default {}

Named instructions an operator can switch a thread to with Thread.setOutputStyle. Pinned with the agent config; keys and texts non-empty. Omitted: no styles.

Returns

DynamicAgent<Deps, Output>

Throws ConfigError for a definition that can't run.

Edit on GitHub

On this page