第2章 Kortix 连接器详解:配置外部工具与账户管理
连接
连接和连接(connections)赋予 Agent 对受限定范围的外部工具的访问权限。连接器(Connector)将项目与外部工具或服务关联起来,Agent 会将其作为工具进行调用。Kortix 代理每次调用,因此沙箱中不会持有连接器的凭据。
你通常在 kortix.yaml 中声明大部分连接器,或者在 imports 下列出的文件中声明。请查阅清单参考文档了解所有字段。当连接聊天平台或机器时,Kortix 会自动声明渠道(channel)和计算机(computer)连接器。
浏览并添加连接器 打开“连接器”以浏览托管目录。其默认列表包含可通过提供商托管认证或启用的自定义认证配置进行连接的托管提供商工具包。它不需要项目中已有的连接。若工具包需要未经认证的自定义 OAuth 配置,在该配置得到验证之前,它将被隐藏。
对于直接数据源,请在项目的特性标志(feature flags)中启用 Connectors API Discover,然后在同一页面选择 API / MCP。启用该标志不会取代托管默认项。直接目录将已发布的 OpenAPI、MCP、GraphQL、Postman 及其他 API 界面分组展示。选择一张卡片,选择一个已发布的界面,并完成其连接表单。仅含文档的界面将打开提供商的文档页面;它们不会作为可即时连接的模板呈现。
对于目录中不包含的原始 API 或模式,使用“添加 → 手动”。直接发现功能在没有配置托管提供商的情况下也可正常工作。
连接器、连接与账户 连接器是面向 Agent 的访问包:一种已声明的能力(哪些操作、如何访问服务)。它并非角色,且不持有 Kortix 权限:只有当清单授权列表中列出了该 slug,且角色判定允许该调用时,Agent 才能访问连接器。参见“一套词汇,两种绑定”。 连接器包含: * 项目内唯一的 slug * 显示名称 * 提供商应用 * 连接器策略
连接是连接器针对某一个账户(即经过授权的身份)的凭据:OAuth 授权或 API 密钥。一个连接器可以同时持有多账户。每个账户都使用连接器的策略。 每个账户的 owner_type 决定了谁可以以该身份运行调用: * project——共享账户。连接器所授予的任何人员均可访问,无论是人类还是服务账户(Agent、触发器)。 * member——私有账户,归属于单个项目成员(owner_id)。仅限该成员在私有会话中访问。服务账户(无人值守运行的 Agent 或触发器)绝不能以成员的私有账户身份运行。
多个连接器可以引用同一个提供商应用。如果一个应用需要不同的策略,请使用不同的连接器。
添加账户 在“自定义 → 连接器”中打开连接器。“账户”选项卡在一个列表中展示你可以使用或管理的所有账户。每张卡片显示谁可以使用该账户:仅限你、项目内所有人,或与其共享的组和人员。 选择“添加账户”,为账户命名,并选择“谁可以使用”: * 仅限你——私有账户。任何成员都可以添加。 * 项目内所有人——共享账户。 * 特定人员或组——共享账户,但仅限于你选择的人员、组和 Agent。
上述两个共享选项需要 project.connector.connections.manage 权限。对于“特定人员或组”,Kortix 会在你授权该账户之前写入授权,因此该账户不会在整个项目开放期间持有凭据。账户名称必须是新名字:如果同一所有者下的其他账户已使用该名,将被拒绝。
当 Agent 需要账户时,它会在聊天中发布一张“连接”卡片。卡片打开相同的对话框,其中已填入 Agent 建议的名称,并预选其所需的受众。Kortix 会创建一个新账户,绝不重新授权现有账户,并告知 Agent 新账户的名称,以便其能以该账户身份运行调用。
选择谁可以使用共享账户 共享账户默认在项目内对所有人开放,直到你对其进行限定。在账户卡片上选择“共享”。对话框与用于 Agent 的“授予访问”对话框相同。它列出当前谁可以使用该账户,你可以添加: * 项目内所有人——默认项。 * 组——每个组的所有成员。 * 人员——每个单个成员。仅选择自己可将账户保留给自己。 * Agent——该 Agent 的每个会话,包括触发器和共享会话。任何能运行该 Agent 的人都可以经由其使用账户。
未选择“保存”前,任何变更均不生效。移除最后一个组或人员后,账户将对所有人再次开放;对话框会在你保存前说明这一结果。
受限账户遵循私有账户规则,但其受众取代了所有者: * 受众中的人员可以使用它,且仅限在私有会话中。 * 受众中的 Agent 可以其在所有会话中使用它。 * 任何其他 Agent,以及任何其他 Agent 的触发器,绝不能使用它。 * 绑定该账户的会话无法共享,除非该账户也共享给了该会话所属的 Agent。 * 只有人员可以改变谁可以使用账户。Agent 会话会收到 403 错误。
受众之外的人员看不到该账户。管理项目连接的人员仍能看到它,并标记为“未与你共享”,以便他们可以更改谁可以使用它。
共享你自己的私有账户 你自己的“仅限你”账户也有“共享”按钮。共享后,它将变为你选择的人员和组(除非移除自己,否则你仍保留在内)或项目内所有人的共享账户。从此,它就是一个共享账户:管理项目连接的人员也可以管理它。 共享需要 project.connector.connections.manage 权限,与添加共享账户相同。若无此权限,按钮将被禁用并说明原因。Kortix 先写入授权,然后在一次更新中将账户转为共享,因此在中间状态它绝不会对整个项目开放。同名共享账户在该连接器上会阻断共享(409):请先重命名其中一个。
POST /projects/{projectId}/connections/{connectionId}/share
{"principals": [{"principal_type": "group", "principal_id": "
空的 principals 列表表示共享给所有人。在 CLI 中:
kortix connectors connections share
每个受众条目都是授权存储中的一次连接对象分配:
POST /accounts/{accountId}/iam/assignments
{"principal_type": "group", "principal_id": "
在 CLI 中,相同的写入操作为:
kortix access grant --group
principal_type 为 user、group 或 project(项目内所有人;principal_id 为项目 ID)。 授予或撤销某一项需要 project.connector.connections.manage 权限。只有共享账户可以通过这些授权进行限定。私有账户,或非本项目中连接项的 ID,会返回 404;请改用上述共享路由共享你自己的私有账户。 GET /projects/{projectId}/connections 在 shared_with 中返回每个共享账户的授权,并对调用者仅能管理而不能使用的账户返回 usable: false。会话选择器仅提供可用账户。
账户以何种身份操作
账户的标签是在授权前选定的名称。它并未说明使用了哪个登录身份。connected_as 字段说明了这一点:提供商报告该授权账户的电子邮件、登录名或显示名称。
当 Composio 授权完成时,Kortix 读取此字段:先读取已连接账户的显示名称,然后读取工具包的“我是谁”工具(Gmail、Google Calendar、Google Drive、Linear、GitHub、Slack、Notion、Outlook、Microsoft Teams、HubSpot、Jira、Asana、Figma、Airtable、Salesforce、Trello、Dropbox、Calendly)。Google Docs 和 Google Sheets 未公开此类工具,因此其 connected_as 保持为 null。
若账户仍带有默认标签(私有连接、项目连接或连接器名称),它会重命名为该身份。用户选定的标签绝不被替换。
连接页面在账户落地瞬间即显示“已连接为……”,因此以个人登录授权的共享账户立即可见。
connected_as 出现在所有连接中(GET /projects/{projectId}/connections)、账户列表、kortix connectors accounts
重命名账户
无需重新授权即可重命名账户:
PUT /projects/{projectId}/connections/{connectionId}/label {"label": "Support inbox"}
kortix connectors connections rename
连接不同账户 若插槽已持有有效账户,其连接链接不会重新授权。提供商将重用该账户,连接页面显示“已连接”。若要使用不同的登录身份,请在连接器上添加新账户,将其设为默认,然后断开旧账户。 未指定账户的调用首先解析为调用者自己的默认私有账户,其次是项目的默认共享账户。每个调用结果都会回显其运行所用的账户(account: { connection_id, label, owner_type }),因此转录总是显示工具调用使用的身份。 使用 GET /connectors/projects/{projectId}/connectors/{slug}/accounts 或 SDK 中的 kortix.project(projectId).connectors.accounts(slug) 列出连接器可被调用的账户,默认项在前。
提供商 连接器使用一种提供商类型: * composio——受支持的 SaaS 应用的托管 OAuth * pipedream——遗留托管 OAuth,仅用于回滚 * openapi, postman, graphql, http——直接 API 连接器 * mcp——通过 HTTP 或 SSE 的远程 MCP 服务器 * channel——聊天平台连接 * computer——每个成员连接的机器即是一个账户
参见 Slack 与渠道以及计算机了解托管提供商流程。
需要自有 OAuth 应用的应用 Composio 持有大多数工具包的自有 OAuth 应用。对于部分应用则未持有:X (twitter)(自 2026 年 2 月起),以及仅限 OAuth 的工具包,如 xero、spotify、google_chat、googleforms 和 zoom_chat。截至 2026-09-26,共有 47 个。除非 Composio 项目持有包含你自有 OAuth 应用的认证配置,否则 Composio 无法连接它们。 在存在该认证配置之前,连接器目录不会列出该工具包。已为其声明的连接器在同步时会因 422 composio_auth_config_required 失败,消息中会指明该工具包。 要启用其中一个,请在提供商处注册 OAuth 应用。在 Composio 仪表板中,打开“认证配置”,为该工具包创建认证配置,并输入应用的客户端 ID 和密钥。将仪表板显示的跳转 URI 添加到提供商应用中。 Kortix 会自行找到已启用的认证配置。你无需重启或重新部署。目录会在 60 秒内列出该工具包。下一次同步和连接将立即使用该认证配置。 若某工具包存在多个已启用的认证配置,Kortix 使用最新的一个。禁用旧配置以轮换 OAuth 应用。 使用自有应用连接的 Composio 工具包将继续使用该应用。Kortix 绝不会为其选择认证配置。
认证与策略 连接通过以下方式认证: * 通过 Composio、渠道安装或原生 OAuth2 授权的 OAuth * 通过仪表板或 SDK 输入的 API 密钥或令牌
Kortix 加密连接数据并在服务器端为每个工具调用解析它。Agent 请求操作。Kortix 附加凭据,检查 Agent 授权和连接器-连接策略,调用外部 API,并返回结果。 连接器策略归属于连接器。连接不能覆盖它们。项目护栏应用于连接器-连接策略之上。 默认情况下,未匹配的连接器操作无需审批即可运行。将 policy.default_mode 设为 risk 以要求对未匹配的写入和破坏性操作进行审批。将 sensitive 设为 true 可使 require_approval 成为连接器未匹配操作的默认设置(包括读取)。显式的项目或连接器-连接规则仍优先适用。
审批一次受管调用 require_approval 为一次连接器调用创建一个决定。连接器返回 202 pending_approval,包含 approval_url、approval_summary 和 execution_id。它不会保持 HTTP 请求打开。 将 approval_url 分享给任何团队成员。该 URL 标识请求但不授予权限。页面需要登录的 Kortix 账户。Kortix 随后验证该账户能否在项目中访问并审批操作。 审批页面显示连接器将接收的脱敏参数。 调用者可以添加 approval_context(CLI:--reason)来描述影响。当参数仅为引用时使用此功能:gmail.send_draft 接收草稿 ID,因此 Agent 需说明收件人、主题和正文。页面将此文本显示为 Agent 的描述,而非经过验证的内容。参数仍是证据。Kortix 绝不将 approval_context 发送给提供商。 一次性审批或拒绝该调用。可给决定添加可选消息。消息将随决定返回给 Agent,以便拒绝时可说明替代方案。 每个待处理调用也会显示在项目的“审阅 → 需要你”中。从侧边栏打开“审阅”;其计数显示有多少项在等待你。调用在与其审批链接相同的审批视图中打开,以便你在决定前看到连接器、参数和 Agent 描述。 若调用来自 Slack 或 Teams 会话,Kortix 在该线程中发布审批卡片。卡片显示 Agent 描述、参数以及“批准/拒绝”。在 Slack 中,“回复…”打开一个发给 Agent 的消息框;在 Teams 中,消息框在卡片内联。只有项目经理或发起会话的人可以做出决定。在任何地方(线程、Kortix 或审批页面)做出的决定都会将卡片按钮替换为结果,Agent 在同一线程继续。Kortix 通过持久回调将决定发回会话。审批仅适用于确切的请求摘要。更改收件人、主题、正文、渠道、URL 或其他参数需要新的决定。 打开会话的审计面板以使用相同的参数视图。历史条目保持只读。没有会话范围的审批选项。仅当连接器操作必须无人值守运行时,才使用显式的 always_run 策略。
通过 OAuth 连接 打开项目的连接器页面 打开项目。选择“连接器”,然后选择应用。 选择账户范围 选择“项目”作为共享账户,连接器授予的任何人员均可访问。选择“用户”作为私有账户,由你拥有且仅限你在私有会话中访问。 完成授权 完成 OAuth 流程。Kortix 将已连接账户存储为连接。
连接使用 OAuth 2.1 的 MCP 服务器
Kortix 实现了 MCP 授权规范。打开连接器,选择“添加凭据”,然后选择“OAuth 2.0”选项卡。Kortix 探测服务器并读取其元数据:
* 未认证探测返回 401,带有 WWW-Authenticate: Bearer resource_metadata="…"。
* Kortix 读取该 URL 或 /.well-known/oauth-protected-resource 处的受保护资源元数据(RFC 9728)。
* Kortix 读取资源指定的第一个授权服务器的授权服务器元数据(RFC 8414 或 OpenID Connect 发现)。
当该服务器公布 registration_endpoint 时,Kortix 注册自身为 OAuth 客户端(RFC 7591)并显示一个按钮:连接
从 CLI 授权 仪表板是运行此流程的方式之一,并非唯一方式。在 kortix.yaml 中声明连接器,然后从终端或 Agent 会话中授权: connectors: - slug: read-ai name: Read AI provider: mcp url: 'https://api.read.ai/mcp' auth: type: bearer kortix connectors authorize read-ai --json 该命令创建连接,运行发现链,若服务器支持 RFC 7591 则注册 Kortix 为客户端,并返回待批准的 URL: { "connection_id": "7b1a16b2-...", "registered": true, "scopes": ["openid", "offline_access", "mcp:execute", "meeting:read"], "authorization_url": "https://authn.read.ai/oauth2/auth?response_type=code&...", "expires_at": "2026-08-19T14:48:26.345Z" } Agent 将 authorization_url 返回给正在合作的人员。待其批准后,Agent 确认: kortix connectors authorize read-ai --status 当状态为 error 时,该命令以非零状态退出。使用 --scope 以限定请求内容。对于不支持动态客户端注册的服务器,使用 --client-id 和 --client-secret。 SDK 中也可用相同步骤——discoverConnectionOAuth2Resource、registerConnectionOAuth2Client、startConnectionOAuth2Authorization 和 getConnectionOAuth2Status。 授权完成时,Kortix 立即重新获取连接器的工具目录,因此连接器无需手动同步即可脱离错误状态。
自托管:为机器提供稳定的公共 URL
回调 URL 派生自 KORTIX_URL,即你 API 的公共源。授权服务器按字节比较 redirect_uri,因此该值必须稳定。
以零配置快速隧道启动的自托管安装会在 cloudflared 每次重启时获得新的 https://
通过 OAuth2 连接直接 API 直接连接器支持: * 客户端凭据 * 带 PKCE 的授权码 * 设备授权 * 动态客户端注册(RFC 7591) 对于客户端凭据,请输入令牌 URL、客户端 ID、作用域和客户端密钥。你可以使用 client_secret_basic、client_secret_post、client_secret_jwt 或 private_key_jwt 令牌端点认证。 对于授权码,请输入授权 URL 和令牌 URL。对于设备授权,请输入设备授权 URL 和令牌 URL。RFC 8414 发现 URL 可提供这些端点。 Kortix 加密 OAuth2 配置和令牌。它在到期前刷新访问令牌,并存储每个轮换后的刷新令牌。撤销连接会阻止下一次连接器调用。 对于 Microsoft Graph,请使用: https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token https://graph.microsoft.com/.default 对于直接 SharePoint REST 调用,请使用 SharePoint 资源作用域: https://{tenant}.sharepoint.com/.default
通过 API 密钥连接 声明连接器 connectors: - slug: stripe-read name: Stripe read access provider: openapi spec: 'https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.json' auth: type: bearer policies: - match: 'get_*' action: always_run - match: '*' action: block 清单仍接受 authorization_strategy 键以兼容旧版。Kortix 忽略它:改为在添加凭据时按连接设置所有者(共享或私有)。 合并变更请求 Kortix 从默认分支读取清单。连接器在变更请求合并后生效。 添加连接 打开连接器并设置其凭据。Kortix 以加密方式存储该值。它不会将值写入清单。
授予 Agent 访问权限 将连接器 slug 添加到 Agent 的 connectors 字段: agents: release-bot: connectors: [stripe-read] 省略 connectors,Agent 将无权访问任何连接。合并变更后才能生效。 connectors_required 已弃用。清单仍接受它,但没有内容读取它:在创建时绝不会因连接器无可用的账户而拒绝会话。实际中因缺少连接器而拒绝创建会话的情况无法触及——仅私有的连接器没有共享账户可提供,因此拒绝没有调用者可采取的补救措施。现在的门槛是连接器调用:被授予 stripe-read 的 Agent 可以立即开始其回合,只有实际需要使用连接器的调用才可能被拒绝(参见“当调用被拒绝时”)——并附带补救措施。
选择账户 有两种独立方式选择调用运行所用的账户——为整个会话固定一个,或在单次调用中指定一个。 固定会话范围的默认值 会话可以覆盖连接器的默认账户,应用于其发出的所有调用: { "connector_bindings": { "stripe-read": { "connection_id": "00000000-0000-4000-8000-000000000000" } } } 绑定键是连接器 slug。值是该会话调用者有权访问的账户(连接)。 使用 GET /projects/{projectId}/sessions/{sessionId}/scope 读取有效绑定。使用相同路径的 PUT 替换它。替换应用于下一个工具调用,无需重启会话。 在一次调用中指定账户 使用 GET /connectors/projects/{projectId}/connectors/{slug}/accounts 列出连接器可被调用的账户——默认项在前: { "connector": "stripe-read", "accounts": [ { "connection_id": "...", "label": "Shared workspace", "owner_type": "project", "is_default": true, "connected_as": "billing@example.com" }, { "connection_id": "...", "label": "My Stripe", "owner_type": "member", "is_default": false, "connected_as": null } ] } 然后在调用中通过连接 ID 或标签(不区分大小写)指定一个,或使用两个选择词 me(你自己的默认私有账户)和 project(项目的默认共享账户): kortix connectors call stripe-read get_balance '{}' --account me kortix connectors call stripe-read get_balance '{}' --account "Shared workspace" 未指定账户的调用首先解析为调用者自己的默认私有账户,其次是项目的默认共享账户——这与连接器可持有多账户之前保持不变。无法解析的指定账户将被拒绝,绝不会静默替代为其他账户(参见“当调用被拒绝时”)。每个成功调用结果都会回显其运行所用的账户:account: { connection_id, label, owner_type }。
在会话中使用连接器
在会话内,使用连接器 CLI:
kortix connectors ls
kortix connectors accounts stripe-read
kortix connectors call stripe-read
大型结果 列表或搜索调用可能返回超过模型可读取的内容:超过约 50 KB 的工具输出会被截断。将结果保存到文件并使用代码处理: kortix connectors call linear graphql.issues '{"first":250}' --out /workspace/output/issues.json # → { "ok": true, "account": …, "saved_to": "/workspace/output/issues.json", # "bytes": 93037, "shape": { "issues": { "nodes": "array(250) of {id,title,…}", # "pageInfo": { "hasNextPage": true, "endCursor": "…" } } } } jq '.data.issues.nodes[] | {id, title}' /workspace/output/issues.json --out 写入完整的 JSON 结果,并创建父目录。标准输出获得不含 data 的调用信封,外加 saved_to、bytes 和 shape:data 的轮廓(键、数组长度以及所有 pageInfo)。退出码不变。 kortix-connectors MCP 工具调用在没有标志的情况下执行相同操作。大于 16 KB 的结果保存在 /workspace/.kortix/state/connector-results/ 下,工具返回 { saved_to, bytes, shape, preview, hint },带有约 2 KB 的预览。该目录在 git 中忽略自身。较小的结果内联返回。
附加文件 调用绝不会在参数中携带文件字节。先暂存文件,然后在参数中放入其引用。网关在服务器端读取字节并将其写入请求。 kortix connectors call microsoft-graph.sendmail @mail.json \ --attach /workspace/artifacts/report.pdf --attach 暂存文件并在操作的 attachments 数组中附加引用。数组在操作的输入模式中找到:Email 渠道为 attachments,Microsoft Graph sendMail 为 body.message.attachments。若模式异常,使用 --attach-path body.message.attachments 指定名称。 大型 JSON 参数放入文件(@mail.json)或通过标准输入(-)。 若要自行放置文件,请先暂存: kortix connectors upload /workspace/artifacts/report.pdf --connector microsoft-graph # → { "attachment_id": "…", "ref": { "$kortix_attachment": "…" }, … } 将 ref 放在参数任何位置。网关按位置替换: ref 的位置 | 替换为 attachments 数组的元素(若项为对象) | 提供商的附件项。项模式选择形状:Microsoft Graph fileAttachment(name + contentBytes 或 @odata.type)、Postmark(Name + Content)、Mailjet(Filename + Base64Content)、SendGrid 和 Resend(filename + content)、Brevo(name + content)。其他项形状以 attachment_item_shape_unknown 拒绝。 字符串字段,例如 contentBytes 或 GitHub 文件内容 | 文件的 base64。 Email 渠道的 attachments[] | Email 提供商的签名下载 URL。 规则: * 文件来自 /workspace/output、/workspace/artifacts、/workspace/reports 或 /workspace/deliverables。拒绝符号链接和硬链接。请先将文件复制到那里。 * 一次调用最多携带 20 个文件,总计 25 MiB。上游 API 可设置更低限制:Microsoft Graph 文档指出单个 sendMail 请求可附加的最大文件为 3 MB。 * 暂存文件对暂存它的会话私有,使用一次,并在 24 小时后删除。调用失败会释放以供重试。 * 审计记录、审批预览和模型仅看到引用,永远看不到字节。回显文件的上游错误会移除 base64。 Pipedream 和 Composio 连接器不接受暂存文件(connector_attachments_unsupported)。 MCP 服务器提供相同流程:call 接受 attachment_files(以及可选的 attachment_path),upload_attachment 返回 ref。SDK 等效项为 connectors.uploadAttachment(bytes, { filename, contentType, connector }),返回 ref。
当调用被拒绝时 被拒绝的调用返回 { ok: false, status: "denied", reason, hint }。reason 是稳定代码;hint 说明应对措施。 reason | HTTP | 含义 | 正文中还包含 connector_not_assigned | 403 | 运行中 Agent 的 kortix.yaml 中的 connectors: 授权不包含此连接器。 | agent, granted(列表或 "all"),manifest_revision 和 manifest_commit(授权来源的清单)。 connector_not_connected | 403 | 此调用没有可用账户。要么连接器对此调用者根本没有账户(无存储凭据,或应用从未授权——kortix connectors ls 显示为 needs_auth),要么 --account 指定了无法解析的一个。 | connect_url——调用者可铸造时,用于授权账户的托管链接——在无连接时。requested_account 和 available_accounts——未解析的名称和可用的名称——当 --account 指定时。 connector_disabled | 403 | 连接器已声明但被禁用。 | — connector_not_found | 404 | 项目中未声明此 slug 的连接器。 | — action_not_found | 404 | 连接器无此操作。 | — connect_url 是未连接连接器的全部补救措施:会话绝不会因一个未连接的连接器而被预先拒绝(参见“授予 Agent 访问权限”),因此拒绝本身携带修复方法。Agent 原样展示链接;Web 转录将其渲染为单点击的“连接”按钮。该链接默认授权打开它的人员使用私有账户——连接共享账户是显式选择(kortix connectors connect stripe-read --owner project,受 project.connector.write 限制)。 创建会话的渠道连接器(Slack、Teams、电子邮件)始终可从该会话调用,无论 Agent 的授权如何,因此 Agent 总能报告在其被询问的线程中。 会话的授权遵循 kortix.yaml:对运行中 Agent 的 connectors: 的更改(包括 kortix connectors add --apply)在下一次调用时生效。授权记录其来源的清单 blob 和提交;来自同一 blob 的读取需经第二次读取确认才能替换,来自较旧提交的读取绝不替换它。 Slack 和 Microsoft Teams 通过仪表板连接的方式与 OAuth 应用相同。连接 Slack 会为你将渠道连接器写入 kortix.yaml。参见“Slack & 渠道”。