Echolot
参考

工作区文件

逐个文件、逐个键地说明工作区格式,可用于阅读差异、手写文件和生成文件。

工作区是一个以 .echolot 结尾的文件夹,里面是纯文本的 TOML 文件:每个请求、环境、MCP 服务器、模拟服务器和流程各一个。访达把它显示为一个文档;在“终端”、Git 和你的编辑器中,它是一个普通文件夹。Echolot 每次都以相同的方式写入每个文件(键的顺序固定,取默认值的项不写入),因此 App 中的一处更改,在差异中也只是一处小改动。参见 Git 和团队。

Alpenglow.echolot/
  workspace.toml                     the workspace: ID, name, variables, auth, agents, proxy, certificates
  environments/
    staging.toml                     one environment
  requests/
    _folder.toml                     the order of the top level
    _folder.pre.js                   the workspace's pre-request script (and _folder.test.js)
    auth/
      _folder.toml                   a folder: name, order, docs, variables, auth
      sign-in.req.toml               an HTTP request
      sign-in.body.json              its body
      sign-in.pre.js                 its pre-request script
      sign-in.test.js                its test script
    catalog/
      search-products.gql.toml       a GraphQL request
      search-products.graphql        its query
  mcp-servers/
    alpenglow-mcp.toml               an MCP server
  specs/
    alpenglow.yaml                   an OpenAPI document
    shop.graphql                     a GraphQL schema
    inventory.proto                  a protobuf file
  mocks/
    shop.toml                        a mock server: settings and routes
    shop.js                          its routes in JavaScript
  flows/
    place-test-order.flow.toml       a flow
  assistant/
    checking-orders.md               a shared Assistant conversation, to read
    checking-orders.json             the same, to open in the app

所有文件的规则

  • 文件是 TOML 1.0,UTF-8 编码。
  • 每个文件都以 echolot = 1 开头,这是格式的版本号。版本号更高的文件是由更新的 Echolot 存储的,Echolot 会提示这一点,而不会打开它。
  • 文件名是 slug:小写字母、数字和连字符,最多 80 个字符,由项目的名称生成(Sign in 对应 sign-in)。名称本身存放在 name 键中。
  • 项目之间的路径是以 / 连接的 slug,相对于 requests/:auth/sign-in、orders。
  • 文本字段可以包含 {{variables}} 和动态值。
  • 事物的列表是 TOML 的表数组([[headers]])。带有 enabled = false 的内容会保留但处于关闭状态;没有该键则表示开启。

绝不会写入文件的内容

  • 机密值。机密变量只写入名称和 secret = true,不含值;值存放在你 Mac 的钥匙串中。需要机密的字段(密码、代理密码、客户端机密)应写成一个属于机密的 {{variable}}。Echolot 会提示把你输入的密码移到钥匙串中,导入时则自动这样处理。参见机密。
  • OAuth 令牌和 MCP 登录信息:在钥匙串中。
  • 脚本用 pm.environment.set 等设置的值:它们只在窗口或命令的存续期间有效。
  • 历史记录和响应:存放在你 Mac 的 Application Support 中,每个工作区一份历史记录。参见历史记录。
  • 你自己的布局:窗格布局及其大小、打开的标签页、你选择的环境。

因此工作区可以放心地提交和共享。同事需要设置他们自己的机密值。

workspace.toml

# Echolot workspace. Requests live in requests/, one file each.
echolot = 1
id = "0b7d4c1e-2f6a-4e38-9c51-7a1e3d9b5f20"
name = "Alpenglow"

[[variables]]
name = "baseURL"
value = "https://demo.echolot.dev/v1"

[[variables]]
name = "token"
secret = true
键含义
id工作区的 ID。钥匙串中的机密属于它,因此 ID 相同的副本会共享这些机密。导出的副本会得到新的 ID。
name工作区的名称。
[[variables]]工作区变量。参见变量。
[auth]对所有继承它的请求生效的认证。参见认证。默认:无。
[agents]AI 智能体的规则。参见智能体。
[proxy]工作区自己的代理,取代 App 的代理。
[[certificates]]要信任的 CA 证书和要发送的客户端证书,按主机设置。

代理

键含义
modemanual(默认)、system、environment(HTTPS_PROXY 一类的变量)或 none。
url代理:http://host:port、https://… 或 socks5://host:port。
username、password代理的凭据。请把密码写成属于机密的 {{variable}}。
bypass直接访问的主机,是一个数组。

证书

每个 [[certificates]] 表是针对一个主机的规则:

键含义
host规则所针对的主机。
trust要信任的 CA 证书的 PEM 文件,是一个数组。
certificate客户端证书:一个 PEM 文件,或一个 .p12/.pfx 文件。
key客户端证书的 PEM 密钥,用于证书文件中不含密钥的情况。
passphrase密钥或 PKCS#12 文件的口令。请把它写成属于机密的 {{variable}}。

智能体

[agents] 设置 AI 智能体通过 Echolot 的 MCP 服务器和助手在此工作区中可以做什么。参见智能体。

[agents]
allowed-hosts = ["demo.echolot.dev"]
max-requests = 200
max-requests-per-minute = 30

[agents.rules]
unsafe-send = "ask"
destructive = "refuse"
键含义
enabledfalse 会为该工作区关闭智能体:它们从中什么也得不到。默认为 true。
allowed-hosts除其请求所用的主机外,也算作工作区自己的主机。
max-requests一次智能体会话总共可以发送的请求数。
max-requests-per-minute一次智能体会话每分钟可以发送的请求数。
[agents.rules]每类操作一条规则:allow、ask 或 refuse。

操作的类别有 read、safe-send、unsafe-send、protected-send、new-host、workspace-write 和 destructive。更严格的规则始终有效。较宽松的规则只有在你信任之后才生效(App 会询问;命令行需要 --trust-workspace-policy)。protected-send 和 new-host 永远不能设为 allow。

environments/

每个环境一个文件;文件名就是它的 slug,供 --env 使用。

echolot = 1
name = "Production"
protected = true

[[variables]]
name = "baseURL"
value = "https://api.alpenglow.example/v1"

[[variables]]
name = "password"
secret = true
键含义
name环境的名称。
protectedtrue 使其成为受保护的环境:每次发送都会先询问。
[[variables]]它的变量。

变量

在 workspace.toml、环境、文件夹和请求中都相同:

键含义
name变量的名称,以 {{name}} 的形式使用。
value它的值。机密变量省略此项。
secrettrue 表示机密:值在钥匙串中。
enabledfalse 将其关闭。

requests/

requests 文件夹保存你在边栏中看到的树。其中每个文件夹是树中的一个文件夹,每个请求文件是一个请求。请求的种类由文件的后缀决定:

后缀种类
.req.tomlHTTP,包括 Server-Sent Events
.gql.tomlGraphQL
.grpc.tomlgRPC
.ws.tomlWebSocket
.sio.tomlSocket.IO
.mqtt.tomlMQTT
.mcp.toml对 MCP 服务器的调用

与请求并列、使用相同 slug 的文件:

文件内容
<slug>.body.<ext>请求正文,采用其自身的格式:.json、.xml、.txt、.html、.graphql 或 .form.txt。
<slug>.graphqlGraphQL 请求的查询。
<slug>.pre.js请求前脚本。
<slug>.test.js测试脚本。

_folder.toml

每个文件夹都有一个,requests/ 本身也有一个,用于顶层。

echolot = 1
name = "Auth"
order = ["sign-in", "who-am-i", "client-credentials"]
docs = "Send \"Sign in\" first: it captures the access token into {{token}}."
键含义
name文件夹的名称。requests/_folder.toml 中没有此项。
order文件夹中各项的 slug,按边栏和运行使用的顺序排列。未列出的内容排在后面,按 slug 排序。
docs文件夹的文档,使用 Markdown。
spec文件夹所遵循的规范,例如 specs/alpenglow.yaml。
spec-url该规范从哪里获取,用于它来自某个 URL 的情况。
agent-toolstrue 会把文件夹中的请求作为工具提供给智能体。
[[variables]]文件夹的变量,对其中的一切生效。
[auth]文件夹的认证,对其中所有继承它的内容生效。默认:继承。

与它并列的 _folder.pre.js 和 _folder.test.js 是文件夹的脚本;在 requests/ 中则是工作区的脚本。它们会对其中的每个请求运行,从工作区的开始,直到请求自己的脚本。遵循某个规范的文件夹还有 _spec-lock.json,记录它上次从规范中取走的内容;请让 Echolot 来维护它。

所有请求的键

echolot = 1
name = "Sign in"
method = "POST"
url = "{{baseURL}}/auth/token"

[body]
syntax = "json"
file = "sign-in.body.json"

[[headers]]
name = "Content-Type"
value = "application/json"

[[assertions]]
target = "status"
check = "equals"
expected = "200"

[[captures]]
variable = "token"
from = "json"
path = "$.access_token"
scope = "workspace"
secret = true
键含义
name请求的名称。
urlURL,含查询字符串。除 MCP 调用外,每种请求都有。
docs请求的文档,使用 Markdown。
spec-operation它所依据的规范操作,例如 POST /auth/token。
[[headers]]name、value,以及对已关闭的标头设置 enabled = false。
[[disabled-params]]已关闭的查询参数:name、value。开启的参数在 URL 中。
[[disabled-form-fields]]已关闭的表单字段:name、value。
[[variables]]请求自己的变量。
[[assertions]]它的检查。
[[captures]]每次响应之后存入变量的值。
[auth]它的认证。默认:继承所在文件夹的认证。
[settings]与 App 不同的设置。

HTTP 请求(.req.toml)

键含义
method方法:GET、POST 或任意标记。默认为 GET。
[body]正文;省略则没有正文。

[body] 表有三种形式之一:

形式键
文本syntax:json、xml、text、html、graphql 或 form(URL 编码的表单字段)。file:与请求并列的正文文件。
从磁盘流式传输的文件stream-from:文件的路径。
Multipartsyntax = "multipart",每个部分一个 [[body.parts]] 表:name,然后是 value(文本)或 file(路径)、content-type、enabled。

GraphQL 请求(.gql.toml)

echolot = 1
name = "Search products"
url = "{{baseURL}}/graphql"
operation = "SearchProducts"
schema = "specs/shop.graphql"
query-file = "search-products.graphql"
graphql-variables = """
{
  "text": "ultralight"
}"""
键含义
query-file与请求并列、保存查询的文件,<slug>.graphql。
operation查询包含多个操作时,要运行的操作。
graphql-variablesGraphQL 变量,作为 JSON 文本。较旧的文件称之为 variables。
schema用来检查和补全的 Schema:specs/ 中的一个文件。
transportpost(默认)、get,或用于订阅的 websocket。
persisted-queriestrue 会先只发送查询的 SHA-256,服务器不认识时再发送查询(自动持久化查询)。
batchtrue 会把包含多个操作的文档作为一个数组发送,每个操作一项。
[[uploads]]文件上传:variable(文件所对应的变量)和 path。

gRPC 请求(.grpc.toml)

键含义
proto描述服务的 .proto 文件,例如 specs/inventory.proto。
reflectiontrue 表示改为询问服务器的反射。
service服务,例如 alpenglow.inventory.v1.Inventory。
rpc方法,例如 Reserve。
message消息,作为 JSON 文本;客户端流式方法则为消息数组。
deadline-ms截止时间,以毫秒计。
compression所发送消息的压缩方式:gzip 或 deflate。

WebSocket 请求(.ws.toml)

键含义
subprotocols要提供的子协议,是一个数组。
[[messages]]已存储的消息:name、text、enabled。

Socket.IO 请求(.sio.toml)

键含义
version服务器的 Socket.IO 版本:4(默认)、3 或 2。
path服务器监听的位置。默认为 /socket.io/。
namespace要加入的命名空间,例如 /support。
socket-auth认证载荷,作为 JSON 文本。
[[emits]]已存储的事件:name、event、arguments(JSON 文本)、ack = true 表示要求确认,以及 enabled。

MQTT 请求(.mqtt.toml)

键含义
version5(默认)或 3.1.1。
client-id客户端 ID;为空时随机生成。
clean-startfalse 要求 Broker 保留会话。默认为 true。
keep-alive两次 ping 之间的秒数。默认为 60。
[will]遗嘱消息:topic、payload、qos、retain。
[[subscriptions]]filter、qos(默认 0)、no-local、enabled。
[[messages]]要发布的已存储消息:name、topic、payload、qos、retain、content-type、enabled。

用户名和密码是请求的 Basic 认证。

MCP 调用(.mcp.toml)

echolot = 1
name = "search_catalog"
server = "alpenglow-mcp"
tool = "search_catalog"
arguments = """
{
  "query": "ultralight tent",
  "limit": 3
}"""
键含义
server服务器在 mcp-servers/ 中的 slug。
tool、resource、prompt 或 method要调用什么:按名称调用工具、按 URI 调用资源、按名称调用提示词,或原始的 JSON-RPC 方法。只能选其一。
arguments参数,作为 JSON 文本。

断言

键含义
target检查的对象:status、header、json、body、time(毫秒)、size(字节)、schema(JSON Schema)、graphql-errors、mcp-error、mcp-output-schema、openapi、grpc-status。
name对 header:标头的名称。
path对 json:一个 JSONPath,例如 $.items.length。
checkequals、not-equals、contains、not-contains、less-than、at-most、greater-than、at-least、exists、not-exists、matches(正则表达式)、is-type、is-one-of、matches-schema。
expected用来比较的值;不需要值的检查不写入。
enabledfalse 将其关闭。

每个对象可用哪些检查,参见脚本和测试。

捕获

键含义
variable用来存放值的变量。
fromjson、form、msgpack、xml、header、cookie、status 或 body。
path值所在的位置:JSONPath、XPath、标头或 Cookie 的名称。status 和 body 不需要。
scopeenvironment(默认:当前环境)或 workspace。
secrettrue 会把值作为机密存放在钥匙串中。
enabledfalse 将其关闭。

状态码为 400 或更大的响应,或不存在的值,都会让变量保持原样。参见捕获。

设置

键含义
timeout整个交换的秒数。
rawtrue 表示不发送自动添加的标头。
verify-tlsfalse 跳过证书验证。
follow-redirectsfalse 在重定向处停止。
max-redirects最多跟随多少次重定向。
decompressfalse 让正文保持服务器编码后的样子。
cookiesfalse 表示既不发送也不存储 Cookie。
http-versionautomatic、http1、http2 或 http3。
stream-limit监听事件流或会话的秒数。

参见请求设置。

认证

[auth] 有一个 type,以及该类型的键。没有 [auth] 的请求或文件夹会继承;工作区的默认值是不认证。

type键
inherit无:采用文件夹的认证。
none无:不认证,即使文件夹有认证。
basic、digestusername、password
bearertoken;不是 Bearer 时用 prefix
api-keyname、value、in(header 或 query)
oauth2grant(authorization-code、client-credentials、device-code)、authorization-url、token-url、device-authorization-url、client-id、client-secret、scope、audience、redirect-uri;pkce = false 关闭 PKCE;client-authentication = "body" 把客户端凭据放在正文中发送,而不是使用 Basic;不是 Bearer 时用 header-prefix
aws-signatureaccess-key-id、secret-access-key、session-token、region、service
jwtalgorithm(HS256、HS384、HS512、RS256、RS384、RS512、PS256、PS384、PS512、ES256、ES384)、secret、secret-base64、payload、header、issued-at = false 省略 iat、expires-in(秒,默认 300)、in(header 或 query)、prefix、query-name(默认 token)
hawkid、key、algorithm(sha256 或 sha1)、ext、payload-hash
edgegridclient-token、client-secret、access-token、max-body(默认 131072)、headers-to-sign
ntlmusername、password、domain、workstation

请把每个密码、令牌和密钥都写成属于机密的 {{variable}}。参见认证。

mcp-servers/

每个 MCP 服务器一个文件;文件名就是 MCP 调用所引用的 slug。

echolot = 1
name = "Alpenglow MCP"
transport = "http"
url = "https://demo.echolot.dev/mcp"
键含义
name服务器的名称。
transporthttp(Streamable HTTP)或 stdio(由 Echolot 启动的程序)。
url对 http:端点。
[[headers]]对 http:name、value、enabled。
command对 stdio:要启动的程序。
arguments对 stdio:它的参数,是一个数组。
working-directory对 stdio:它启动时所在的文件夹。
[[environment]]对 stdio:环境变量,name、value、enabled。
[oauth]用 OAuth 登录的服务器的客户端设置:client-id、client-secret、scope、redirect-uri。

参见添加服务器。

specs/

规范文件保持原样:OpenAPI 文档(.yaml、.yml、.json)、GraphQL Schema(.graphql SDL,或 JSON 格式的内省结果)和 protobuf 文件(.proto)。Echolot 就地编辑它们并保留你的格式。请求和模拟服务器通过路径引用它们,例如 specs/alpenglow.yaml。参见规范。

mocks/

每个模拟服务器一个文件,其 JavaScript 路由与它并列。

echolot = 1
name = "Shop"
spec = "specs/alpenglow.yaml"
port = 4010
delay = 200

[[scenarios]]
operation = "GET /products/{sku}"
status = "404"

[[routes]]
id = "e5f6a7b8"
method = "GET"
path = "/users/{id}"
summary = "One user"

[[routes.responses]]
name = "OK"
status = 200
content-type = "application/json"
headers = [{ name = "X-Request-Id", value = "{{$randomUUID}}" }]
body = """
{
  "id": "{{request.params.id}}",
  "name": "{{$randomFullName}}"
}"""

[[routes.responses]]
name = "Not found"
status = 404
content-type = "application/json"
rules = [{ source = "path", name = "id", value = "0" }]
body = """{ "error": "no user {{request.params.id}}" }"""
键含义
name模拟服务器的名称。
spec它提供服务的规范。没有它,则只有模拟服务器的路由会应答。
port端口。默认为 4010。
share-on-networktrue 会在每个网络接口上应答,而不只是这台 Mac。
delay每次应答前的毫秒数。
failure-rate被注入 500 应答的请求所占的百分比,0 到 100。
validate-requestsfalse 会应答违反规范的请求。默认为 true。
[[scenarios]]为规范的某个操作选定的应答:operation(例如 GET /pets)、status、example(示例的名称)。
[[routes]]手动创建的路由:id(路由更改时保持不变)、method(或 ANY)、path(参数写作 {id})、summary、对已关闭的路由设置 enabled = false、response(默认响应的名称;省略则为第一个)、request-content-type 和 request-body(根据它创建的请求所发送的内容)。
[[routes.responses]]上述路由的一个应答:name、status、content-type、headers(name 和 value)、rules(source 为 path、query、header 或 body;name;value,* 表示任意值,空表示没有)和 body。

mocks/<slug>.js 保存模拟服务器的 JavaScript 路由,它们先于手动创建的路由和规范应答。对于规范的操作,响应从不存放在模拟服务器中:示例要放进规范。参见模拟服务器、路由和示例数据和 JavaScript 路由。

flows/

每个流程一个文件,<slug>.flow.toml。Echolot 以固定的顺序写入块、连线和备注,因此移动一个块只会改动两行。

echolot = 1
name = "Place a test order"
description = "Places an order, then asks a person whether to keep it."

[mcp]
tool = "place_test_order"
description = "Places a test order on the demo shop, asking a person before keeping it."

[[blocks]]
id = "signin"
kind = "request"
title = "Sign in"
position = [330, 250]

[blocks.settings]
request = "auth/sign-in"

[[wires]]
from = "start.run"
to = "signin.run"
键含义
name、description流程的名称和它的作用。
[mcp]把流程作为工具提供给智能体:tool(它的名称)和 description。
[schedule]按计划运行:every-minutes,或 cron(例如 "0 6 * * *")。
[webhook]在请求到达时运行:method(默认 POST)和 path。
[[inputs]]它的输入:name、type(any、text、number、bool、object、list、secret)、description、default、required。
[[blocks]]它的块:id、kind、title、position(画布上的 [x, y])、paused、color,以及带有该种类设置的 [blocks.settings]。
[[wires]]连线:from 和 to,各为 block.port。
[[groups]]块的分组:title、blocks(它们的 ID)、color。
[[notes]]画布上的备注:text、frame([x, y, width, height])。

块的种类及其设置见块。

assistant/

你在工作区中共享的与助手的对话:<slug>.md 供在任何编辑器中阅读,<slug>.json 供 Echolot 再次打开。

其他文件

Echolot 不认识的文件会被保持不动,因此 README、.gitignore 或数据文件可以放在工作区中。智能体或流程保存的数据(例如 exports/products.csv)会放在要求它放的位置,位于工作区之内。

本页内容