Skip to content

Options 与 HostConfig ​

Options 描述 agent 本身;HostConfig 描述它跑在什么样的部署里。源码:packages/noeta-sdk/noeta/client/options.py 和 client/host_config.py。

python
from noeta.sdk import Client, HostConfig, Options
from noeta.sdk.providers import AnthropicProvider

options = Options(
    system_prompt="You are a careful coding agent.",
    permission_mode="acceptEdits",
    max_turns=40,
)
host = HostConfig(storage_path="noeta.sqlite", write_mode="apply")

with Client(options, provider=AnthropicProvider(), model="claude-sonnet-5", host_config=host) as client:
    client.start(goal="Fix the failing test in tests/test_utils.py")

Options ​

一个不可变的 dataclass。字段分两类:身份字段会编译进记录下来的 AgentSpec,改了就算另一个 agent;接线字段 compile_options 不看,== 比较也不算,所以换 provider、换目录都不改变 agent 身份。

身份字段 ​

字段类型默认值说明
system_promptstr | SystemPromptPreset必填提示词原文,或一个预设名
namestr"main"agent 名字,不能和 agents 里的键重名
skillstuple[str, ...]()给这个 agent 开的技能
budgetBudgetSpec | NoneNone上限;None 等于 BudgetSpec(max_subtask_depth=3)
pluginstuple[str, ...]DEFAULT_PLUGINS = ("fs", "web")这个 agent 启用的插件(见下文)
agentsMapping[str, AgentDefinition]{}子 agent,一层平铺的 dict
allowed_toolstuple[str | tool, ...] | NoneNone整体替换工具列表;None 是 10 个内置工具,() 是一个都没有
disallowed_toolstuple[str, ...]()从当前工具列表里去掉;不存在的名字直接忽略
permission_modestr"default"default / acceptEdits / bypassPermissions
max_turnsint | NoneNonebudget.max_iterations 的简写;两个都设会抛 ValueError
policy带 .ref 的 (llm) -> PolicyNone替换内置的 ReAct 循环
mcp_serverstuple[SdkMcpServer, ...]()进程内 MCP server,工具会并入工具列表

10 个内置工具是 Read、Write、Edit、Glob、Grep、Bash、BashOutput、KillShell、WebFetch、WebSearch(WebSearch 只在设了 NOETA_WEB_SEARCH_API_KEY 时出现)。见工具。

接线字段 ​

字段类型默认值说明
providerLLMProvider | NoneNone模型适配器;Client(provider=...) 优先
modelstr | NoneNone主循环用的模型 id 或别名
compaction_modelstr | NoneNone只用来写上下文压缩摘要的便宜模型;None 就用 model
recall_modelstr | NoneNone关键词没召回到记忆时,用这个模型再判断一次;None 只做关键词召回
webfetch_modelstr | NoneNoneWebFetch 读网页时用来总结的模型;None 用主模型
metadataMapping[str, str]{}给 observer 看的标签
cwdstr | Path | NoneNoneClient 没给 workspace_dir 时用的工作目录
can_use_tool(tool_name, arguments) -> boolNone用代码批准或拒绝需要审批的调用;记录里 resolver="can_use_tool"
output_schemaMapping | NoneNone最终答案的 JSON Schema;答案会解析成 dict / list(解析不了就保留原文)
thinking"adaptive" | "disabled" | NoneNone推理模式;None 用 provider 默认
effort"low" | "medium" | "high" | "xhigh" | "max" | NoneNone推理强度
guardstuple[Guard, ...]()动作执行前的检查,可以拦下
observerstuple[Observer, ...]()每个事件提交后的回调
content_channelstuple[ContentKindSpec, ...]()额外常驻上下文的内容块

thinking / effort 取值不对会在构造时抛 ValueError;thinking="disabled" 配 effort="xhigh" 或 "max" 也会抛(Anthropic 不接受这个组合)。

AgentDefinition ​

一个子 agent。不能嵌套:所有 agent 都在 Options.agents 顶层声明。

字段类型默认值说明
descriptionstr必填在 Task 工具里给父模型看;空白会抛 ValueError
promptstr必填子 agent 的提示词
toolstuple | NoneNoneNone 是内置工具
modelstr | NoneNone子 agent 用的模型;None 用宿主默认
pluginstuple[str, ...]()没有 fs/web 默认值;("delegation",) 让它也能派子 agent
metadataMapping[str, str]{}标签,不算身份

SystemPromptPreset ​

字段类型默认值说明
presetstr"main"用 register_preset_prompt(name, prompt) 注册过的名字(后注册的覆盖先注册的)
appendstr | NoneNone空一行后追加的文字

main 和 main-web 已经注册好了,见 Presets。

BudgetSpec ​

字段都默认 None(不设上限):max_iterations、max_tool_calls、max_cost_usd、max_spawned_subtasks、max_subtask_depth。计数覆盖任务整个生命周期,不按轮清零。

compile_options ​

python
compile_options(options, *, plugins=None, preset_prompts=None)
    -> tuple[AgentSpec, tuple[AgentSpec, ...]]

纯函数:相同的 Options 编出相同的 spec。plugins 是插件名到 PluginActivation 的映射(Client 会从 PluginSet 生成);preset_prompts 用来替换进程级的预设表,编译结果就不受别处注册的影响。

审批模式 ​

模式执行前要审批的
default所有 risk_level 不是 low 的工具
acceptEdits同上,但 Edit 和 Write 不用
bypassPermissions都不用

Bash 和 WebFetch 还会按单次调用判断:命令不在 shell 白名单里,或网址不在 HostConfig.webfetch_allowed_hosts 里,就要审批(bypassPermissions 下除外)。任何模式下 Guard 都还能拦。

合法取值在运行时读,顺序就是界面上该显示的顺序:

python
from noeta.sdk import effort_modes, model_capabilities, permission_modes

permission_modes()   # ('default', 'acceptEdits', 'bypassPermissions')
effort_modes()       # ('low', 'medium', 'high', 'xhigh', 'max')
model_capabilities(["claude-sonnet-4-6", "gpt-4o-mini"])
# {'claude-sonnet-4-6': {'supports_vision': True}, 'gpt-4o-mini': {'supports_vision': False}}

目录里没有的模型,supports_vision 报 True。

启用插件 ​

Options.plugins 列出这个 agent 用哪些插件,名字会记进 AgentSpec.plugins。名字只能是下面几种:

类别名字
内置功能(会打开对应能力)memory、browser、mcp、todo_write、ask_user_question、skill_invocation、delegation
内置但不影响 agent(认得这些名字,是为了让拼错能报错)app、fs、governance、presets、providers、react、reminders、sandbox、skills、storage、web、workspace
已加载的插件传给 Client 的 PluginSet 里的任意名字
python
from noeta.sdk import DEFAULT_PLUGINS, Options

Options(system_prompt="...", plugins=DEFAULT_PLUGINS + ("memory", "todo_write"))
# plugins=("memry",) 编译时报错:
#   ValueError: unknown plugin activation 'memry' on Options — not a built-in activation (...)

agents 不为空时会自动加上 delegation;手动写它只会打开、不会关掉。去掉 fs/web 不会少掉默认工具,但记录下来的身份会变。

HostConfig ​

一个不可变 dataclass,通过 Client(..., host_config=...) 传入,永远不算 agent 身份。HostConfig() 就是内存存储、不用沙箱、不接 MCP。

存储 ​

字段类型默认值说明
storage_pathstr | NoneNonesqlite 文件路径、postgresql:// 连接串,或 ":memory:"
event_log、content_store、dispatcher适配器None直接传存储对象;三个要么都给,要么都不给
queuestr"default"共享存储时这个 client 的 worker 队列;它的 worker 只领这个队列的活

storage_path 和三个对象同时给,或三个只给了一部分,都会抛 ValueError。noeta.sdk.storage.open_storage_stack(path) 用一个字符串建出这三个对象;同一模块还导出 build_storage_stack、is_memory_path、is_postgres_url 以及 Sqlite / Postgres 适配器。

模型调用与 MCP ​

字段类型默认值说明
provider_headers(StepContext) -> Mapping[str, str]None每次模型请求额外带的请求头(比如网关的粘性标识)
delta_sink(StepContext, call_id, StreamDelta) -> NoneNone流式 provider 的实时 token 增量;不落盘
extra_modelsMapping[str, ModelSpec]{}追加到模型目录的条目;重名会报错;每次运行都要注册同样的条目
mcp_server_resolver(alias) -> McpAnyServerSpec | NoneNone每轮把 MCP 别名解析成 server 配置
mcp_http_postHttpPostFnNone远程 MCP 用的自定义 HTTP 传输
mcp_idle_ttlfloat | None1800.0池里没人用的 MCP 连接保留多少秒;None 永不关闭
mcp_scope_resolver(task_id) -> str | NoneNone连接池分区(比如租户 id);只有同一分区的任务才共用连接
otlp_tracesOtlpTraceConfigNoneOTLP/HTTP 链路导出:endpoint、headers=()、service_name="noeta"
otlp_http_post函数None导出用的自定义传输

沙箱 ​

字段类型默认值说明
exec_envSandboxExecEnvConfigNone接到一个共用的容器:base_url、api_key_env="SANDBOX_API_KEY"、workdir="/workspace"
sandbox_providerSandboxProviderNone每个根任务一个新容器;优先于 exec_env
sandbox_specSandboxSpecNone每次分配时固定的部分:image、mounts、resources、env
sandbox_exec_preamble(exec_env_ref, argv) -> strNone每条命令前现算的 shell 前缀(用来带上新鲜的凭证)
sandbox_backend_factory、sandbox_browser_factory工厂函数None替换沙箱或浏览器的客户端实现
sandbox_policy(root_task_id, workspace_dir) -> boolNone返回 False 时这个任务在本机跑
app_gatewayAppPreviewGatewayNone打开 open_app 预览工具
write_roots(task_id) -> Sequence[str]None任务在工作目录之外还能写的目录
write_mode"dry_run" | "apply""dry_run""apply" 才会真正写文件;其他值直接报错

记忆 ​

记忆目录的优先级:memory_root_resolver > memory_dir > global_memory_dir > ~/.noeta/memories。见按租户隔离记忆。

字段类型默认值说明
memory_dir、global_memory_dirPath | NoneNone宿主级的记忆目录
memory_root_resolver(task_id) -> Path | NoneNone按任务决定记忆目录;同一任务每次必须返回同样的结果
recall_excludeCollection[str]()自动召回永远不带的页面(索引里仍能看到,也能读)
memory_max_bytesint | NoneNonememory_write 正文超过这么多 UTF-8 字节就拒绝;建议小于 4096,这样召回时能整页带上
memory_read_onlyboolFalse只给 memory_read 和 memory_search
memory_index_budget_tokensint | NoneNone记忆索引的长度上限;None 是上下文窗口的 1%

技能与插件 ​

字段类型默认值说明
skill_menu_rank_resolver(task_id) -> {skill: score} | NoneNone技能菜单超长时,哪些技能保留完整描述
skill_usage_rankingboolTrue没有 resolver 时按整个存储里的近期使用排序;设了记忆或 MCP 分区 resolver 时自动关闭
plugin_configMapping[str, Mapping[str, Any]]{}给各插件的运维配置;对 fs / skills / workspace / memory,你给的键逐个覆盖 SDK 自己算出来的

技能菜单占上下文窗口的 1%。超了就先把描述缩成一句话,再不够就只留名字,排名低的先缩。静态排序可以直接写在 plugin_config["skills"]["menu_rank"],和 resolver 二选一。

限制与开关 ​

字段类型默认值说明
repetition_thresholdint | NoneNone同样的 (tool, arguments) 调用重复这么多次后要审批;必须是正数
tool_output_inline_limitint | NoneNone工具结果超过这么多字符就截断再给模型看(完整内容仍有记录);必须是正数;恢复任务时要保持同一个值
webfetch_allowed_hostsSequence[str]()WebFetch 不用审批就能访问的站点:"example.com" 精确匹配,"*.example.com" 只匹配子域名;写错会报错
workflow_allowedboolFalse提供 run_workflow(还需要能派子 agent)
max_background_jobs_per_root_taskint8后台 Bash 任务超过这个数直接拒绝
max_background_subagents_per_root_taskint8Task(background=True) 同理
environment_enabledboolTrue任务开始时记录工作目录 / git / 平台信息
instructions_enabledboolFalse从工作目录根加载 NOETA.md,没有就 AGENTS.md,再没有就 CLAUDE.md
instructions_filePath | NoneNone只加载这个文件,不再查找
instructions_discoveryboolFalseagent 读到子目录时,也加载那里的说明文件

WARNING

webfetch_allowed_hosts 只管要不要弹审批。WebFetch 自己不拦任何地址,出网限制要在网络层或沙箱里做。

接线用到的类型 ​

名字说明
SandboxProviderProtocol:allocate / release / attach
SandboxSpec、MountSpec分配容器的输入;MountSpec(source, target, mode="rw", kind="local-path"),kind 可选 local-path / nas / volume / pvc
SandboxHandle一个在用的容器:base_url、sandbox_id、auth、workdir="/workspace"
SandboxAuth、StaticApiKeyAuthconnect_headers() Protocol 和读环境变量的实现
encode_exec_env_ref、decode_exec_env_ref记录下来的容器引用的编解码
ExecEnv、BrowserBackend命令执行和浏览器的 Protocol
BackendFactory、BrowserBackendFactory、BoundPreamble沙箱工厂字段的类型
McpServerSpec、McpHttpServerSpec、McpAnyServerSpecmcp_server_resolver 的返回值(stdio、HTTP、二者之一)
HttpPostFn、McpHttpResponse、McpError、McpConfigErrorMCP 传输和错误
OtlpTraceConfig链路导出配置
path_within(resolved, root) -> bool写入围栏用的路径包含判断,按路径分段比较(/srv/app-old 不在 /srv/app 里面)

下一步 ​

基于 Apache License 2.0 发布。