carto-create-builder-maps

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

carto-create-builder-maps

carto-create-builder-maps

CARTO Builder is a mapping tool that renders interactive maps from a JSON map configuration. This skill covers the full authoring lifecycle via the CLI: create from natural language, edit datasets / layers / widgets / popups / privacy, publish snapshots for shared viewers, validate offline, and operate via the
carto maps
commands. It also covers cross-profile copy (
dev → prod
promotion, customer-segregated org delivery via
carto maps copy
/
maps clone
) — see the Promote / copy across orgs references below.
For ad-hoc spatial SQL exploration, use
carto-query-datawarehouse
.
Field shapes, enum values, palette catalogues, and AI-tool catalogues are served by the CLI — never hardcode or assume them. Run
carto maps schema [section]
for JSON Schema (generated from the same Zod definitions Tier-1 validation uses),
carto maps agents models
/
mcp-tools
/
core-tools
for AI surfaces, and
carto connections describe <conn> <table>
for dataset metadata. When this doc disagrees with the CLI, the CLI wins.
CARTO Builder 是一款可通过JSON地图配置渲染交互式地图的制图工具。本技能涵盖了通过CLI完成的完整地图创作生命周期:从自然语言请求创建地图、编辑数据集/图层/小部件/弹窗/隐私设置、为共享查看者发布快照、离线验证,以及通过
carto maps
命令进行操作。同时还支持跨配置文件复制(通过
carto maps copy
/
maps clone
实现从开发环境到生产环境的迁移、按客户隔离的组织交付)——详情请参阅下方的「跨组织迁移/复制」参考文档。
如需进行临时空间SQL探索,请使用
carto-query-datawarehouse
字段结构、枚举值、调色板目录和AI工具目录均由CLI提供——切勿硬编码或主观假设。运行
carto maps schema [section]
获取JSON Schema(由一级验证使用的Zod定义生成),运行
carto maps agents models
/
mcp-tools
/
core-tools
查看AI相关功能,运行
carto connections describe <conn> <table>
获取数据集元数据。若本文档与CLI内容冲突,以CLI为准。

References

参考文档

Decision / orientation — read first
  • references/cartography.md
    — cartographic decisions ahead of styling: palette family, scale type, basemap pairing, multi-layer hue separation, anti-patterns. Mandatory reading before writing JSON when styling decisions are in scope.
  • references/configuration-shape.md
    — the JSON skeleton, annotated.
    keplerMapConfig
    top-level structure +
    datasets[]
    entries (table / query / tileset / raster) +
    mapSettings
    rules.
  • references/examples.md
    — working templates validated against a live organization: minimal map, H3 aggregation, SQL parameters, widgets gallery. Load when you need a JSON template to start from.
Per-component — consult on demand while authoring
  • references/layers.md
    — per-layer-type authoring:
    tileset
    (point / line / polygon / 3D),
    h3
    ,
    quadbin
    ,
    heatmapTile
    ,
    clusterTile
    ,
    raster
    . Plus colour ranges (palettes / scales /
    /stats
    ) and basemap-aware contrast.
  • references/widgets.md
    — analytical surface:
    formula
    ,
    category
    ,
    pie
    ,
    histogram
    ,
    range
    ,
    timeseries
    ,
    table
    . Ordering, collapsibility defaults, cross-filtering across datasets.
  • references/popups.md
    popupSettings
    covers two interaction surfaces: tooltip popups (hover / click) AND info panels (docked side panel, click-only). 5-field hover cap, custom HTML templates with inline CSS, what the renderer sanitises out.
  • references/sql-parameters.md
    Category
    ,
    DateRange
    ,
    Numeric
    ,
    NumericRange
    .
    {{paramName}}
    placeholder authoring + provider-native dialect translation.
  • references/basemap.md
    — write BOTH
    basemapConfig.styleId
    AND
    mapStyle.styleType
    to the same value (the screenshot engine + viewer SSR still read
    mapStyle
    today). CARTO basemaps / Google Maps / custom basemap catalogue.
  • references/agent-config.md
    — Agent on a map (opt-in). Organization-status check, model selection, MCP / core tool catalogues, capability-driven activation.
Operate / unstick
  • references/updates.md
    — CRUD lifecycle: recipes, the partial-vs-wholesale
    keplerMapConfig
    rule (the #1 destructive footgun),
    --datasets-mode
    , publish chaining, validation levers.
  • references/troubleshooting.md
    — symptom → fix table, antipatterns to avoid emitting, escape-hatches when stuck, visual verification via
    carto maps screenshot
    .
Promote / copy across orgs — read when migrating maps between profiles
  • references/cross-profile-copy.md
    maps copy
    and
    maps clone
    mechanics, connection mapping (
    --connection-mapping
    /
    --connection
    ),
    --skip-source-validation
    , what transfers vs. what doesn't.
  • references/agent-migration-caveats.md
    UNAVAILABLE_MODEL
    /
    UNAVAILABLE_TOOL
    issues after copying a map with an AI agent, why the CLI can't auto-fix them, the manual Builder steps.
  • references/post-copy-validation.md
    — confirm the destination map renders correctly: datasets, connections, agent issues, destination URL construction.

决策/定位——优先阅读
  • references/cartography.md
    — 样式设计前的制图决策:调色板系列、缩放类型、底图搭配、多图层色调区分、反模式。在涉及样式决策编写JSON前,必须阅读本文档。
  • references/configuration-shape.md
    — 带注释的JSON框架。
    keplerMapConfig
    顶层结构 +
    datasets[]
    条目(表格/查询/瓦片集/栅格) +
    mapSettings
    规则。
  • references/examples.md
    — 经过真实组织验证的可用模板:极简地图、H3聚合、SQL参数、小部件展示库。当你需要JSON模板作为起点时可参考。
按组件分类——创作时按需查阅
  • references/layers.md
    — 按图层类型创作:
    tileset
    (点/线/面/3D)、
    h3
    quadbin
    heatmapTile
    clusterTile
    raster
    。还包括颜色范围(调色板/缩放/
    /stats
    )和底图感知对比度。
  • references/widgets.md
    — 分析界面:
    formula
    category
    pie
    histogram
    range
    timeseries
    table
    。排序规则、默认折叠设置、跨数据集交叉筛选。
  • references/popups.md
    popupSettings
    涵盖两种交互界面:工具提示弹窗(悬停/点击)和信息面板(停靠侧边栏,仅点击触发)。悬停最多显示5个字段、带内联CSS的自定义HTML模板、渲染器会清理的内容。
  • references/sql-parameters.md
    Category
    DateRange
    Numeric
    NumericRange
    {{paramName}}
    占位符创作 + 原生方言转换。
  • references/basemap.md
    — 将
    basemapConfig.styleId
    mapStyle.styleType
    设置为相同值(当前截图引擎和查看器SSR仍读取
    mapStyle
    )。CARTO底图/谷歌地图/自定义底图目录。
  • references/agent-config.md
    — 地图上的Agent(可选功能)。组织状态检查、模型选择、MCP/核心工具目录、基于能力的激活。
操作/故障排除
  • references/updates.md
    — CRUD生命周期:操作指南、
    keplerMapConfig
    部分更新与完整替换规则(最易导致破坏性操作的陷阱)、
    --datasets-mode
    、发布链、验证机制。
  • references/troubleshooting.md
    — 症状→解决方案对照表、需避免的反模式、陷入困境时的应急方案、通过
    carto maps screenshot
    进行视觉验证。
跨组织迁移/复制——在配置文件间迁移地图时阅读
  • references/cross-profile-copy.md
    maps copy
    maps clone
    的工作机制、连接映射(
    --connection-mapping
    /
    --connection
    )、
    --skip-source-validation
    、可迁移内容与不可迁移内容。
  • references/agent-migration-caveats.md
    — 复制带有AI Agent的地图后出现的
    UNAVAILABLE_MODEL
    /
    UNAVAILABLE_TOOL
    问题、CLI无法自动修复的原因、手动在Builder中操作的步骤。
  • references/post-copy-validation.md
    — 确认目标地图渲染正常:数据集、连接、Agent问题、目标URL构造。

Authoring process

创作流程

Follow these phases in order for every "create a map" request. Skipping a phase is the most common cause of "the map looks broken in Builder".
对于每一个“创建地图”的请求,请按以下阶段依次进行。跳过某个阶段是导致“地图在Builder中显示异常”的最常见原因。

Phase 1 — Gather context (intake gate)

阶段1——收集上下文(准入环节)

This phase is a gate, not a suggestion. But the order matters: the data is the only fact that constrains what's even askable. Asking the user abstract preferences (audience, mode, widgets, sharing) before knowing what's in the table produces generic questions that often don't apply, and makes the user do the agent's job of mapping wishes to columns.
本阶段是强制准入环节,而非建议。但顺序很重要:数据是唯一能约束需求可行性的事实。在了解表格内容前就询问用户抽象偏好(受众、模式、小部件、共享设置),会产生通常不适用的通用问题,还会让用户承担本该由Agent完成的“将需求映射到列”的工作。

Sequence

步骤

  1. Goal — one line. "What's the map about, and what's the takeaway?" Don't proceed without an answer; "just make a map of X" is fine if X is specific.
  2. Data hint — one line. "Where's the data — a table you already have, a demo dataset, or a file to import?" Resolve to a concrete table FQN before moving on. Demo data: search
    carto-demo-data.demo_tables
    by topic. File: run
    carto imports create
    first.
  3. SILENT data inspection. Before asking anything else:
    • carto connections describe <conn> <table>
      → schema, row count, geom type (point / line / polygon / h3 / quadbin / raster).
    • carto sql query
      for: NULL ratios on candidate
      colorField
      columns, min/max/p50/p95/p99 on numeric columns relevant to the goal,
      COUNT(DISTINCT ...)
      on candidate categorical columns to detect cardinality traps, date range on temporal columns.
    • Cap inspection at one or two queries. Don't audit every column. Inspect what's relevant to the user's goal.
  4. Questions, NOW data-contingent. Only ask what the data makes answerable. Examples of good data-grounded questions versus bad abstract ones:
    Bad (abstract, asked too early)Good (data-grounded, asked after inspect)
    "Want widgets?""I see
    capacity_repd_mwp
    (sum to ~13 GW) and
    repd_status
    (5 categories) — want a capacity total + a status breakdown widget?"
    "Analytical or cartographic?""The table has 23 columns including operational date, area, capacity. Strong analytical map territory — propose a histogram of capacity, or stay simple?"
    "Public or private?"(sharing is orthogonal to data; ask cleanly when relevant — never on first turn)
    "Which palette?""With 265k installations, points will overlap heavily — propose low opacity + uniform colour, or color by capacity (heavy-tailed → log scale)?"
    If the data answers a question on its own, don't ask — just decide:
    • Geom type → layer type, silently: polygon / line / point →
      tileset
      ; pre-indexed h3 / quadbin →
      h3
      /
      quadbin
      directly; raster →
      raster
      .
    • Viewport → bounding box of the data.
    • NULL ratio on a candidate
      colorField
      > 25% → switch column or filter
      WHERE col IS NOT NULL
      silently. See
      cartography.md
      §4.5a
      .
  5. Sharing / audience / agent — ask only when triggered. Don't gate the first map render on these. Default to
    private
    . Surface them when the user says "share with the team", "send to my CEO", "add an AI agent".
  1. 目标——一句话描述“这张地图是关于什么的,核心结论是什么?” 没有答案就不要继续;如果X是具体内容,“就做一张关于X的地图”也可以接受。
  2. 数据提示——一句话描述“数据在哪里——是你已有的表格、演示数据集,还是需要导入的文件?” 在继续前先确定具体的表格完全限定名称(FQN)。演示数据:按主题搜索
    carto-demo-data.demo_tables
    。文件:先运行
    carto imports create
  3. 静默数据检查。在询问其他问题前:
    • carto connections describe <conn> <table>
      → 模式、行数、几何类型(点/线/面/h3/quadbin/栅格)。
    • carto sql query
      查询:候选
      colorField
      列的NULL值比例、与目标相关的数值列的最小值/最大值/p50/p95/p99、候选分类列的
      COUNT(DISTINCT ...)
      以检测基数陷阱、时间列的日期范围。
    • 检查限制在1-2个查询。不要审计每一列,只检查与用户目标相关的内容。
  4. 基于数据的问题。只询问数据能给出答案的问题。以下是好的基于数据的问题与差的抽象问题示例:
    差的问题(抽象,提问过早)好的问题(基于数据,检查后提问)
    “需要小部件吗?”“我看到
    capacity_repd_mwp
    (总和约13 GW)和
    repd_status
    (5个分类)——需要容量总计和状态细分的小部件吗?”
    “分析型还是制图型?”“该表格包含23列,包括运营日期、面积、容量。非常适合做分析型地图——是建议做容量直方图,还是保持简洁?”
    “公开还是私有?”(共享设置与数据无关,在相关时直接询问——不要在第一轮就问)
    “选哪个调色板?”“有26.5万个设施点,点会严重重叠——建议使用低透明度+统一颜色,还是按容量着色(重尾分布→对数缩放)?”
    如果数据能自行回答问题,不要询问——直接决定:
    • 几何类型→图层类型,静默处理:面/线/点→
      tileset
      ;预索引的h3/quadbin→直接使用
      h3
      /
      quadbin
      ;栅格→
      raster
    • 视口→数据的边界框。
    • 候选
      colorField
      的NULL值比例>25%→静默切换列或添加
      WHERE col IS NOT NULL
      过滤。参阅
      cartography.md
      §4.5a
  5. 共享/受众/Agent——仅在触发时询问。不要将这些作为首次地图渲染的前置条件。默认设置为
    private
    。当用户提到“与团队共享”、“发给我的CEO”、“添加AI Agent”时再提及这些设置。

Technical preconditions (silent — don't surface unless they fail)

技术前置条件(静默处理——仅在失败时告知用户)

  • Auth status. Run
    carto auth status
    . If unauthenticated, ask the user to run
    carto auth login
    and stop.
  • Organization AI status (only if the user mentions an Agent on the map).
    carto maps agents status
    — if
    enabled: false
    , drop agent plans and tell the user.
  • 认证状态。运行
    carto auth status
    。如果未认证,要求用户运行
    carto auth login
    并停止操作。
  • 组织AI状态(仅当用户提到地图上的Agent时)。
    carto maps agents status
    ——如果
    enabled: false
    ,放弃Agent计划并告知用户。

Time budget

时间预算

First-version target: ~30s wall time from the user's "go" to a working URL. Achievable when the only intake is goal + data hint and the agent inspects silently. The first map still has to look good — cartographic defaults from
cartography.md
(palette family, scale, basemap pairing, multi-layer hue separation) apply on the first shot; refinement (custom domains, palette swaps, widget tuning) lands on subsequent turns with the user looking at the result.
第一版目标:从用户确认到生成可用URL,耗时约30秒。当仅收集目标和数据提示,且Agent静默检查数据时,这个目标是可实现的。第一张地图仍需美观——
cartography.md
中的制图默认设置(调色板系列、缩放、底图搭配、多图层色调区分)需在首次生成时应用;后续迭代(自定义域、调色板替换、小部件调整)需在用户查看结果后进行。

Phase 2 — Make cartographic decisions

阶段2——制定制图决策

Read
references/cartography.md
ahead of writing JSON when styling is in scope. State explicit choices before emitting:
  • Layer type by data character (point / line / polygon / h3 / quadbin / heatmap / cluster / raster).
  • Palette family (qualitative / sequential / diverging) — pick by narrative + basemap, not reflex.
  • Scale type — pick by data shape AND meaning, not reflex. Default ladder: bounded with semantic landmarks (0–100 scores, %, ratios) →
    quantize
    + explicit
    colorDomain
    matching the natural extent; heavy-tailed across orders of magnitude →
    custom
    +
    uiCustomScaleType: "logarithmic"
    ; skewed unbounded where viewers care about RANK not magnitude →
    quantile
    (the genuine use case, not the safe default); categorical-looking integers → cast to STRING +
    ordinal
    . See
    references/cartography.md
    §3.2 —
    quantile
    is NOT the universal safe default; reflex-picking it on bounded scales like ENERGY STAR / age / % is the most common scale-choice error.
  • Basemap (
    positron
    light default /
    dark-matter
    /
    voyager
    / Google variants / custom).
  • Multi-layer hue separation when there's more than one layer (palette-family-per-layer, not shades of one ramp).
Skip cartography ahead-of-time only on purely structural work (rename, dataset swap, privacy change, agent-config edit, mapSettings tweaks).
当涉及样式设计时,在编写JSON前先阅读
references/cartography.md
。在生成配置前明确说明选择:
  • 图层类型:根据数据特征选择(点/线/面/h3/quadbin/热力图/聚类/栅格)。
  • 调色板系列(定性/顺序/发散):根据叙事和底图选择,而非凭直觉。
  • 缩放类型:根据数据形态和含义选择,而非凭直觉。默认优先级:有语义标记的有界数据(0-100分、百分比、比率)→
    quantize
    +匹配自然范围的显式
    colorDomain
    ;跨数量级的重尾分布→
    custom
    +
    uiCustomScaleType: "logarithmic"
    ;用户关注排名而非数值的偏态无界数据→
    quantile
    (真正适用的场景,而非安全默认);类似分类的整数→转换为STRING+
    ordinal
    。参阅
    references/cartography.md
    §3.2——
    quantile
    并非通用安全默认;在ENERGY STAR/年龄/百分比等有界缩放场景下凭直觉选择它是最常见的缩放选择错误。
  • 底图(默认
    positron
    亮色/
    dark-matter
    /
    voyager
    /谷歌变体/自定义)。
  • 多图层色调区分:当有多个图层时(每个图层使用不同的调色板系列,而非同一渐变的不同色调)。
仅在纯结构性工作(重命名、数据集替换、隐私设置更改、Agent配置编辑、mapSettings调整)时可跳过提前制定制图决策的步骤。

Phase 3 — Compose the configuration

阶段3——编写配置

Reference
references/configuration-shape.md
for the skeleton. Fill in:
  • datasets[]
    — connection, source, geoColumn, type, format. For h3 / quadbin layers see the source-decision rubric (dynamic binning vs pre-built tileset).
  • keplerMapConfig.config.visState.layers[]
    — type + visualChannels + visConfig (consult
    layers.md
    ).
  • keplerMapConfig.config.widgets[]
    if analytical (consult
    widgets.md
    ).
  • keplerMapConfig.config.popupSettings.layers
    — emit by default for feature-identifying datasets (consult
    popups.md
    ).
  • keplerMapConfig.config.sqlParameters[]
    if filterable (consult
    sql-parameters.md
    ).
  • keplerMapConfig.config.basemapConfig
    +
    mapStyle
    — write both, same value (consult
    basemap.md
    ).
  • agent
    block only if the user explicitly asked AND organization AI is enabled (consult
    agent-config.md
    ).
参考
references/configuration-shape.md
获取框架。填充以下内容:
  • datasets[]
    — 连接、源、geoColumn、类型、格式。对于h3/quadbin图层,请参阅源决策规则(动态分箱与预构建瓦片集)。
  • keplerMapConfig.config.visState.layers[]
    — 类型+visualChannels+visConfig(参阅
    layers.md
    )。
  • 如果是分析型地图,添加
    keplerMapConfig.config.widgets[]
    (参阅
    widgets.md
    )。
  • 对于可识别要素的数据集,默认添加
    keplerMapConfig.config.popupSettings.layers
    (参阅
    popups.md
    )。
  • 如果支持过滤,添加
    keplerMapConfig.config.sqlParameters[]
    (参阅
    sql-parameters.md
    )。
  • keplerMapConfig.config.basemapConfig
    +
    mapStyle
    — 两者设置为相同值(参阅
    basemap.md
    )。
  • 仅当用户明确要求且组织AI已启用时,添加
    agent
    块(参阅
    agent-config.md
    )。

Phase 4 — Validate offline

阶段4——离线验证

sh
carto maps validate map.json
Tier-1 catches shape, types, enum values, cross-references, agent fields,
aggregationExp
coherence, privacy coercion, and the dozen-or-so cross-field rules (canonical visualChannels path, custom-marker pairings, popup hover cap, etc.) — all with zero backend calls. Iterate until clean.
sh
carto maps validate map.json
一级验证会检查结构、类型、枚举值、交叉引用、Agent字段、
aggregationExp
一致性、隐私强制设置以及十几个跨字段规则(标准visualChannels路径、自定义标记配对、弹窗悬停上限等)——所有检查无需调用后端服务。迭代直到验证通过。

Phase 5 — Create + verify

阶段5——创建+验证

sh
carto maps create < map.json
The CLI runs Tier-1 + a
SELECT … WHERE 1=0
source-accessibility probe per dataset BEFORE
POST /maps
, so broken sources never create orphan maps. The probe automatically excludes synthetic
_carto_*
columns and post-aggregation aliases parsed from
aggregationExp
, so legitimate h3 / quadbin / heatmapTile / clusterTile authoring won't trip it. After create, decide whether to run
carto maps screenshot <id>
for visual verification — see the "Visual verification" always-on rule below for the decision rubric.
sh
carto maps create < map.json
在执行
POST /maps
前,CLI会运行一级验证并对每个数据集执行
SELECT … WHERE 1=0
源可访问性探测,因此无效源不会创建孤立地图。探测会自动排除从
aggregationExp
解析出的合成
_carto_*
列和聚合后别名,因此合法的h3/quadbin/heatmapTile/clusterTile创作不会触发错误。创建完成后,决定是否运行
carto maps screenshot <id>
进行视觉验证——请参阅下方“视觉验证”的通用规则来决定是否执行。

Phase 6 — Publish (when ready for viewers)

阶段6——发布(准备好供查看者访问时)

maps create
writes a private draft. To make a map visible to the user's intended audience:
  • Set
    privacy
    (
    shared
    with optional
    sharingScope: "organization"
    or
    "specific"
    +
    userIds
    /
    groupIds
    , OR
    public
    ).
  • Run
    carto maps publish <id>
    to freeze a snapshot for shared / public viewers.
  • For chained edit-and-publish:
    carto maps update <id> --publish
    .
Tell the user "it's live for viewers" after a successful publish; otherwise make clear the edits are visible only to them.

maps create
会创建私有草稿。要让地图对用户目标受众可见:
  • 设置
    privacy
    shared
    可选择
    sharingScope: "organization"
    "specific"
    +
    userIds
    /
    groupIds
    ,或
    public
    )。
  • 运行
    carto maps publish <id>
    为共享/公开查看者冻结快照。
  • 如需编辑后直接发布:
    carto maps update <id> --publish
发布成功后告知用户“地图已对查看者开放”;否则明确说明编辑内容仅对用户自己可见。

Always-on rules

通用规则

These apply on every task, not just the create flow.
这些规则适用于所有任务,而非仅创建流程。

Lead with intent — hide the plumbing

以意图为主——隐藏技术细节

When asking the Phase 1 intake questions (and on every follow-up turn), stay in plain language. Do NOT surface
dataId
,
geoColumn
,
tilejson
,
keplerMapConfig
,
connectionId
, FQN syntax, or layer-type taxonomy on turn 1 — that reads as a spec dump and makes the user do your job. Frame every question in terms the user already has: "what's the map about", "who reads it", "should viewers be able to filter", "how should it be shared". Translate to the JSON in your head; don't ask the user to.
在询问阶段1的准入问题(以及后续每一轮交互)时,使用通俗易懂的语言。第一轮不要提及
dataId
geoColumn
tilejson
keplerMapConfig
connectionId
、FQN语法或图层类型分类——这会像技术规范堆砌,让用户承担你的工作。所有问题都要从用户已有的认知出发:“这张地图是关于什么的”“谁会查看它”“查看者是否需要过滤功能”“如何共享”。在脑海中转换为JSON;不要让用户来做这件事。

Do silently, don't ask

静默执行,无需询问

  • Auth — run
    carto auth status
    before the first API-touching command.
  • Connection UUID + FQN syntax — once the user names the table, use
    carto connections list
    and
    carto connections describe
    to resolve. Don't ask the user to hand-type
    project.dataset.table
    .
  • Imports — when the user has a file, not a table — if the user offers a path / URL to a geospatial file (CSV / GeoJSON / GeoPackage / GeoParquet / KML / KMZ / Shapefile-zip, ≤ 1GB), run
    carto imports create --file <path>
    (or
    --url <url>
    )
    --connection <name> --destination <fqn>
    to land it as a warehouse table FIRST, then build the map on the imported table. Defaults: pick a connection from
    carto connections list
    (prefer the user's primary CARTO Data Warehouse if present), pick a sensible
    --destination
    FQN that mirrors the file's basename. The command waits for completion by default; pass
    --async
    only when the user is shipping a multi-GB load they want to background. Don't ask the user to convert formats — the importer handles all 7.
  • Layer type — infer from dataset shape:
    • line / polygon source →
      tileset
      .
    • point source, sparse / feature-level (find-this-store, click-to-zoom) →
      tileset
      .
    • point source, dense / large (the typical aggregation case) → aggregate to
      h3
      or
      quadbin
      (h3 = hex aesthetic, quadbin = square + zoom-adaptive cell size). This is the right default for "where does X cluster?" / "density of Y" questions on a large point table — quantitative reading, comparable across viewports, no per-row render budget pressure.
    • pre-indexed h3 / quadbin source →
      h3
      /
      quadbin
      directly (no aggregationExp needed).
    • band-stored raster →
      raster
      .
    • heatmapTile
      and
      clusterTile
      are NOT silent defaults
      — pick them only when the user explicitly asks for "a heatmap" / "clustered points", OR when the narrative is specifically pattern-without-numbers (
      heatmapTile
      ) or numbered-bubbles-with-zoom-to-individual (
      clusterTile
      ). For everything else where the data is dense points, default to
      h3
      /
      quadbin
      aggregation — they preserve quantitative reading while heatmap blurs it and cluster turns it into bubble counts.
    Only ask the user when the choice between feature-level (
    tileset
    ) and aggregation (
    h3
    /
    quadbin
    ) is genuinely ambiguous — e.g. "individual store locations, or density across the city?".
  • Viewport — centre on the data's bounding box (the CLI computes this during create); don't ask for lat/lng/zoom.
  • Legend & categorical domains — the CLI fetches
    /stats
    and populates the legend automatically.
  • colorField
    data-shape probe
    — before binding a numeric column to
    colorField
    (or
    sizeField
    /
    radiusField
    /
    heightField
    ), check NULL ratio with a one-line
    carto sql query
    probe (
    SELECT COUNT(*), COUNT(col) FROM source
    ). If > 25% of rows are NULL the map renders dominantly grey at render time — same family as the categorical-cardinality trap. Two fixes (no need to ask the user): filter
    WHERE col IS NOT NULL
    in the source SQL, or pick a more-populated column. See
    references/cartography.md
    §4.5a for the worked example. Skip the probe on round-trips of existing maps (the user already chose the column) and on tiny datasets (< 1k rows — the trap doesn't materialise visibly).
  • Popups — emit by default when the dataset has feature-identifying columns (
    name
    /
    id
    /
    address
    /
    owner
    /
    timestamp
    ). End users cannot consult the source table — the popup (or, secondarily, a
    table
    widget) is the ONLY way they can read per-feature attributes. A map without popups and without a table widget shows the user a colour and a position; everything else about the feature is invisible to them. Add hover with 2–4 identifier columns, click with the rest. Skip only on pure pattern maps (heatmap, density h3/quadbin where the read is aggregate, not per-feature).
  • Widgets — propose by default for analytical maps, count by use case (not a fixed number):
    • Pure cartography map: 0 widgets.
    • Operational / "find this feature" map: 1–2 (mostly
      table
      ).
    • Exploratory analytical map: 3–6 (formula + category/pie + histogram + timeseries + range + table).
    • Dashboard map: 6–8. Past ~8 the panel gets crowded.
  • SQL parameters — propose when the source has a natural filter axis (date range, region, category). Wire
    {{paramName}}
    placeholders + a
    sqlParameters[]
    entry +
    mapSettings.sqlParameterControls: true
    . Skip when the source is static.
  • Description — viewer-facing Markdown, OPTIONAL. Empty/omitted descriptions don't render at all for the viewer (the right-rail info button is hidden when description is empty); leaving it empty is fine for reference maps or maps with no story to tell. When you do emit one, go rich — the right rail has plenty of vertical room and a well-built description reads like a small landing page for the map. See
    references/cartography.md
    §6.4 for the full template (optional hero image →
    ## Title
    → lead paragraph → optional
    ### Context
    ,
    ### What you are looking at
    ,
    ### Things to try
    ), the no-tables / no-
    ### Source
    rules, and a worked NYC PLUTO example. Not for authoring notes, agent reasoning, or change history. When you choose to emit nothing, set
    description: ""
    (empty string, never null — null leaks a placeholder);
    maps create
    auto-fills
    ""
    ,
    maps update
    needs an explicit
    ""
    to clear.
  • 认证 — 在执行第一个调用API的命令前,运行
    carto auth status
  • 连接UUID + FQN语法 — 一旦用户指定表格,使用
    carto connections list
    carto connections describe
    来解析。不要让用户手动输入
    project.dataset.table
  • 导入——当用户有文件而非表格时 — 如果用户提供地理空间文件的路径/URL(CSV/GeoJSON/GeoPackage/GeoParquet/KML/KMZ/Shapefile-zip,≤1GB),先运行
    carto imports create --file <path>
    (或
    --url <url>
    --connection <name> --destination <fqn>
    将其导入为数据仓库表格,然后基于导入的表格构建地图。默认设置:从
    carto connections list
    中选择一个连接(优先选择用户的主CARTO数据仓库),选择一个合理的
    --destination
    FQN,与文件的基础名一致。命令默认会等待完成;仅当用户上传多GB文件并希望后台运行时,才添加
    --async
    参数。不要让用户转换格式——导入器支持所有7种格式。
  • 图层类型 — 根据数据集形态推断:
    • 线/面源→
      tileset
    • 点源,稀疏/要素级(查找特定门店、点击缩放)→
      tileset
    • 点源,密集/大数据量(典型聚合场景)→聚合为
      h3
      quadbin
      (h3=六边形样式,quadbin=方形+自适应缩放单元格大小)。这是“X在哪里聚集?”/“Y的密度如何”这类大数据量点表格问题的正确默认选择——支持定量读取,在不同视口下可比较,无每行渲染预算压力。
    • 预索引的h3/quadbin源→直接使用
      h3
      /
      quadbin
      (无需
      aggregationExp
      )。
    • 波段存储的栅格→
      raster
    • heatmapTile
      clusterTile
      不是静默默认选项
      — 仅当用户明确要求*“热力图”*/“聚类点”,或者叙事重点是无数值的模式(
      heatmapTile
      )或带缩放至单个要素的数字气泡(
      clusterTile
      )时才选择。对于其他密集点数据的场景,默认选择
      h3
      /
      quadbin
      聚合——它们保留定量读取能力,而热力图会模糊数值,聚类会将其转换为气泡计数。
    仅当要素级
    tileset
    )和聚合
    h3
    /
    quadbin
    )的选择确实存在歧义时,才询问用户——例如*“是显示单个门店位置,还是城市范围内的密度?”*。
  • 视口 — 以数据的边界框为中心(CLI在创建时会自动计算);不要询问经纬度/缩放级别。
  • 图例与分类域 — CLI会获取
    /stats
    并自动填充图例。
  • colorField
    数据形态探测
    — 在将数值列绑定到
    colorField
    (或
    sizeField
    /
    radiusField
    /
    heightField
    )之前,使用单行
    carto sql query
    探测NULL值比例(
    SELECT COUNT(*), COUNT(col) FROM source
    )。如果超过25%的行是NULL,地图渲染时会以灰色为主——与分类基数陷阱属于同一类问题。两种修复方式(无需询问用户):在源SQL中添加
    WHERE col IS NOT NULL
    过滤,或选择非NULL值更多的列。参阅
    references/cartography.md
    §4.5a中的示例。在现有地图的迭代(用户已选择列)和小数据集(<1k行——陷阱不会明显显现)时可跳过此探测。
  • 弹窗——默认添加:当数据集包含可识别要素的列(
    name
    /
    id
    /
    address
    /
    owner
    /
    timestamp
    )时。最终用户无法查看源表格——弹窗(或次要的
    table
    小部件)是他们读取要素属性的唯一方式。没有弹窗和表格小部件的地图只能向用户显示颜色和位置;要素的其他所有信息对他们都是不可见的。添加悬停弹窗显示2-4个识别列,点击弹窗显示其余列。仅在纯模式地图(热力图、密度h3/quadbin,读取的是聚合而非单个要素)时跳过。
  • 小部件——分析型地图默认建议:根据用例数量选择(固定数量):
    • 纯制图地图:0个小部件。
    • 运营/“查找此要素”地图:1-2个(主要是
      table
      )。
    • 探索性分析地图:3-6个(formula+category/pie+histogram+timeseries+range+table)。
    • 仪表板地图:6-8个。超过8个会导致面板拥挤。
  • SQL参数——当源有自然过滤轴时建议(日期范围、区域、分类)。配置
    {{paramName}}
    占位符+
    sqlParameters[]
    条目+
    mapSettings.sqlParameterControls: true
    。当源是静态数据时跳过。
  • 描述——面向查看者的Markdown,可选。空描述或省略描述对查看者完全不可见(当描述为空时,右侧栏的信息按钮会隐藏);对于参考地图或无叙事的地图,留空即可。当你确实要添加描述时,内容要丰富——右侧栏有足够的垂直空间,完善的描述读起来像地图的小型着陆页。参阅
    references/cartography.md
    §6.4中的完整模板(可选英雄图片→
    ## 标题
    →引言段落→可选
    ### 背景
    ### 你看到的内容
    ### 可尝试的操作
    )、无表格/无
    ### 来源
    规则,以及NYC PLUTO的示例。不要用于创作笔记、Agent推理或变更历史。当你选择不添加描述时,设置
    description: ""
    (空字符串,永远不要设为null——null会显示占位符);
    maps create
    会自动填充
    ""
    maps update
    需要显式设置
    ""
    来清除描述。

Opt-in blocks — emit ONLY when the user has explicitly asked

可选模块——仅在用户明确要求时添加

Don't offer them proactively, don't list them in "what else can I do?" unless the user is clearly exploring:
BlockEmit when…
agent
User asks for an Agent on the map. Run
carto maps agents status
first; drop if disabled.
privacy
(non-private)
User asks to share. Default stays private.
tags
/
description
User supplies them, or the map is being published externally.
collaborative
User asks for other org members to edit, not just view.
Custom palette / 3D / custom markersUser asks for specific styling, or the default looks wrong.
不要主动提供,除非用户明显在探索,否则不要在“我还能做什么?”中列出:
模块添加时机…
agent
用户要求在地图上添加Agent。先运行
carto maps agents status
;如果禁用则放弃。
privacy
(非私有)
用户要求共享。默认保持私有。
tags
/
description
用户提供相关内容,或地图要对外发布。
collaborative
用户要求组织内其他成员可编辑,而非仅查看。
自定义调色板/3D/自定义标记用户要求特定样式,或默认样式不合适。

Validate before you write

编写前验证

When you've assembled a map configuration and want an offline sanity check before burning an API call, run
carto maps validate <map.json>
. Same Tier-1 checks as
create
with zero backend calls. Useful when iterating in a loop or handing the JSON to the user.
当你组装好地图配置,想要在调用API前进行离线 sanity 检查时,运行
carto maps validate <map.json>
。与
create
使用相同的一级验证,无需调用后端服务。在循环迭代或向用户提供JSON时非常有用。

Reload Builder after a write

写入后重新加载Builder

Every write returns as soon as the server accepts the change. Builder loads the map into its in-memory client state once and does not subscribe to server events, so an open
https://<org>/builder/<id>
tab keeps showing stale state until the tab reloads. For remote / external agents (Claude in claude.ai, ChatGPT, MCP clients, anything without local browser access): tell the user. "Map updated. Reload the Builder tab (Cmd/Ctrl+R) to see changes."
每次写入操作在服务器接受更改后立即返回。Builder会将地图加载到内存客户端状态一次,且不会订阅服务器事件,因此打开的
https://<org>/builder/<id>
标签页会一直显示旧状态,直到重新加载标签页。对于远程/外部Agent(claude.ai中的Claude、ChatGPT、MCP客户端、无本地浏览器访问的工具):告知用户。“地图已更新。重新加载Builder标签页(Cmd/Ctrl+R)即可查看更改。”

Visual verification —
carto maps screenshot
, decided by map shape (no need to ask)

视觉验证——
carto maps screenshot
,根据地图形态决定(无需询问)

carto maps screenshot <id>
renders the map to a PNG. Two engines:
  • light
    (default): @deck.gl/carto
    fetchMap
    — fast (~3–8 s), no Chromium needed. No widgets / legends / popups (deck layers + basemap only).
  • full
    : workspace-www
    /viewer
    in Chromium — feature parity with Builder (~10–20 s); first run downloads ~150 MB Chromium via
    npx playwright install chromium
    .
Don't ask the user "want a screenshot?" — they can't tell whether it's worth the latency. Decide based on the map's shape, run it, then embed the resulting PNG inline in the conversation so the user sees what landed without leaving chat. The latency cost is real (~5–20 s on top of the create), so use it deliberately, not reflexively.
Run a screenshot when:
  • The agent just authored a non-trivial map (3+ layers, custom palettes, custom markers, complex widgets, 3D extrusion, custom basemap). Popups don't render on screenshots, so popup-only changes aren't a screenshot trigger.
  • The user reports the map looks blank / wrong / off — confirm what's actually rendering before iterating.
  • Before publishing publicly — sanity-check the public viewer's render.
  • The agent has no other way to see the result (remote / external agents without browser access — Claude in claude.ai, ChatGPT, MCP clients).
Skip the screenshot when:
  • Simple metadata edit (title / description / privacy / tags).
  • Single-dataset rename, column tweak, or other surgical edit on a previously-screenshotted map.
  • The user is iterating fast in front of an open Builder tab and can just reload (
    Cmd/Ctrl+R
    ).
  • The latency would slow a tight feedback loop and the agent already has high confidence in the output.
Engine pick: default to
light
for speed; switch to
full
when the verification depends on widgets or legends (those don't render in
light
— they only show on the Builder/viewer surface that
full
captures). Popups (hover / click / info-panel / custom HTML templates) don't render on screenshots at all — neither engine captures them, so don't pick
full
to verify popup output. When in doubt with high stakes (public publish, complex multi-layer): pay the
full
-engine cost.
See
references/troubleshooting.md
for full screenshot flag reference (
--render-engine
,
--width
,
--height
,
--lat
/
--lng
/
--zoom
,
--hide-overlays
, etc.).
carto maps screenshot <id>
将地图渲染为PNG。两种引擎:
  • light
    (默认):@deck.gl/carto
    fetchMap
    — 快速(约3-8秒),无需Chromium。不显示小部件/图例/弹窗(仅显示deck图层+底图)。
  • full
    :workspace-www
    /viewer
    在Chromium中运行 — 与Builder功能一致(约10-20秒);首次运行会通过
    npx playwright install chromium
    下载约150MB的Chromium。
不要询问用户“需要截图吗?” — 他们无法判断是否值得等待延迟。根据地图形态决定,运行后将生成的PNG嵌入对话中,让用户无需离开聊天即可查看结果。延迟成本是真实存在的(在创建时间基础上增加约5-20秒),因此要谨慎使用,而非凭直觉。
运行截图的场景:
  • Agent刚创作了一张非平凡地图(3个以上图层、自定义调色板、自定义标记、复杂小部件、3D拉伸、自定义底图)。截图不显示弹窗,因此仅更改弹窗的操作无需触发截图。
  • 用户反馈地图显示空白/异常/不正确——在迭代前确认实际渲染内容。
  • 公开发布前——检查公共查看器的渲染效果。
  • Agent无法通过其他方式查看结果(远程/外部Agent,无浏览器访问——claude.ai中的Claude、ChatGPT、MCP客户端)。
跳过截图的场景:
  • 简单元数据编辑(标题/描述/隐私/标签)。
  • 对已截图的地图进行单数据集重命名、列调整或其他精准编辑。
  • 用户在打开的Builder标签页前快速迭代,只需重新加载(
    Cmd/Ctrl+R
    )即可查看。
  • 延迟会打断紧密的反馈循环,且Agent对输出有很高的信心。
引擎选择: 默认使用
light
以提高速度;当验证依赖小部件或图例时(这些在
light
中不显示——仅在
full
捕获的Builder/查看器界面中显示),切换到
full
。弹窗(悬停/点击/信息面板/自定义HTML模板)完全不会在截图中显示——两种引擎都无法捕获,因此不要选择
full
来验证弹窗输出。当高风险场景(公开发布、复杂多图层)存在疑问时,使用
full
引擎。
完整截图参数参考请参阅
references/troubleshooting.md
--render-engine
--width
--height
--lat
/
--lng
/
--zoom
--hide-overlays
等)。

keplerMapConfig
is wholesale-replace, not partial-merge

keplerMapConfig
是完整替换,而非部分合并

Most top-level fields on
maps update
accept partial patches:
title
,
description
,
tags
,
collaborative
,
privacy
,
agent
,
datasets
.
keplerMapConfig
does not.
Sending
{keplerMapConfig: {config: {basemapConfig: {...}}}}
as a "partial update" wipes layers / widgets / sqlParameters / viewport. To change anything inside
keplerMapConfig
, use the read-modify-write cycle:
carto maps get <id> --json > /tmp/m.json
, edit,
carto maps update <id> /tmp/m.json
. The CLI rejects wipe-causing partial updates pre-flight; see
updates.md
for the full merge matrix.
maps update
的大多数顶层字段接受部分补丁:
title
description
tags
collaborative
privacy
agent
datasets
keplerMapConfig
不支持
。发送
{keplerMapConfig: {config: {basemapConfig: {...}}}}
作为“部分更新”会清除图层/小部件/sqlParameters/视口。要更改
keplerMapConfig
内的任何内容,请使用读取-修改-写入循环:
carto maps get <id> --json > /tmp/m.json
,编辑,
carto maps update <id> /tmp/m.json
。CLI会在飞行前拒绝导致清除操作的部分更新;完整合并矩阵请参阅
updates.md

Don't fabricate a map id from a title

不要从标题生成地图ID

If the user refers to a map by name / title rather than UUID:
  1. carto maps list --mine --search "<hint>"
    — narrows to the user's own maps matching the hint.
  2. Exactly one match → use its
    id
    and confirm before writing.
  3. Multiple matches → list them with ids + titles, ask which.
  4. Zero matches → ask if they meant to create a new map.
Never pick a match and write without the user confirming, and never invent a UUID from a title alone.
如果用户通过名称/标题而非UUID引用地图:
  1. carto maps list --mine --search "<hint>"
    — 缩小到用户自己的地图中匹配提示的结果。
  2. 恰好一个匹配项 → 使用其
    id
    并在写入前确认。
  3. 多个匹配项 → 列出它们的id+标题,询问用户选择哪个。
  4. 无匹配项 → 询问用户是否想要创建新地图。
永远不要在未得到用户确认的情况下选择匹配项并写入,也不要仅从标题生成UUID。

Reserve the spec for when the user asks for it

仅在用户要求时提供技术规范

If they say "show me the JSON" / "I'll write it myself" / "what's the schema", open
carto maps schema
+
configuration-shape.md
. Otherwise keep the conversation about their map, not about ours.

如果用户说*“显示JSON”/“我自己写”/“ schema是什么”*,打开
carto maps schema
+
configuration-shape.md
。否则,对话要围绕用户的地图,而非技术规范。

Cheat sheet

速查表

The work is almost always one of three shapes:
I want to…Do this
Create a map from a natural-language request (the common path)Elicit the required inputs from the user (Phase 1), then emit a configuration with just those,
carto maps create < map.json
Edit an existing map — add a dataset, update a layer's style, change privacy, rename, swap basemap, etc.
carto maps update <id> < partial.json
(partial PATCH; unmentioned fields are preserved — except
keplerMapConfig
which is wholesale-replaced)
Duplicate an existing map
carto maps get <id> --json > map.json
, edit,
carto maps create < map.json
Render + sources + agent checks run automatically on every
create
/
update
and surface as warnings — no separate "validate it will render" step needed.
工作通常分为三种类型:
我想要…操作方式
通过自然语言请求创建地图(常见场景)从用户处获取所需输入(阶段1),然后生成包含这些内容的配置,运行
carto maps create < map.json
编辑现有地图——添加数据集、更新图层样式、更改隐私设置、重命名、更换底图等
carto maps update <id> < partial.json
(部分PATCH;未提及的字段会保留——但
keplerMapConfig
会被完整替换)
复制现有地图
carto maps get <id> --json > map.json
,编辑,
carto maps create < map.json
渲染+源+Agent检查会在每次
create
/
update
时自动运行并显示警告——无需单独执行“验证是否可渲染”步骤。

Commands you reach for most

最常用的命令

carto maps list --mine                            # browse what's already there
carto maps get <id> --json                        # read a configuration; pipe back to create/update
carto maps validate [map.json]                    # Tier-1 sanity check, no API calls
carto maps create [map.json]                      # new map from a configuration file
carto maps update <id> [patch.json] [--publish]   # partial update, optional auto-publish
carto maps publish <id>                           # freeze a snapshot for shared/public viewers
carto maps schema [section]                       # JSON Schema reference
carto maps agents status                          # is CARTO AI enabled on this organization?
carto maps screenshot <id>                        # PNG render for visual verification
carto --commands --json                           # full CLI command catalogue (machine-readable)
carto maps list --mine                            # 浏览已有的地图
carto maps get <id> --json                        # 读取配置;可通过管道传递给create/update
carto maps validate [map.json]                    # 一级sanity检查,无需调用API
carto maps create [map.json]                      # 从配置文件创建新地图
carto maps update <id> [patch.json] [--publish]   # 部分更新,可选自动发布
carto maps publish <id>                           # 为共享/公开查看者冻结快照
carto maps schema [section]                       # JSON Schema参考
carto maps agents status                          # 该组织是否启用CARTO AI?
carto maps screenshot <id>                        # 视觉验证用PNG渲染
carto --commands --json                           # 完整CLI命令目录(机器可读)

Inline recipes

内联示例

Duplicate an existing map — most reliable way to produce a working map; the source configuration is already Builder-shaped, so the partial-layer pitfall doesn't apply.
sh
carto maps get <source-map-id> --json \
  | jq '.title = "My copy" | del(.id, .privacy)' \
  > new-map.json
carto maps create < new-map.json
Update only the title (partial PATCH):
sh
echo '{"title":"Better title"}' | carto maps update <map-id> --json
Add one dataset to an existing map (merge mode keeps existing datasets):
sh
carto maps get <map-id> --json > current.json
jq '.datasets += [{"$ref":"extra","type":"table","source":"proj.ds.new_table","connectionId":"<conn-id>","geoColumn":"geom","columns":["geom"],"format":"tilejson","label":"New source"}]' current.json > updated.json
carto maps update <map-id> --json < updated.json
Replace all datasets (destructive — datasets not in the input are deleted):
sh
carto maps update <map-id> --datasets-mode replace --json < map.json
Update a single dataset's source SQL (no
keplerMapConfig
wipe risk):
sh
carto maps datasets update <map-id> <dataset-id> --source "SELECT geom, revenue FROM stores WHERE country = 'ES'"
For longer recipes (full JSON bundles), see
references/examples.md
.

复制现有地图 — 生成可用地图最可靠的方式;源配置已符合Builder格式,因此不会出现部分图层陷阱。
sh
carto maps get <source-map-id> --json \\
  | jq '.title = "My copy" | del(.id, .privacy)' \\
  > new-map.json
carto maps create < new-map.json
仅更新标题(部分PATCH):
sh
echo '{"title":"Better title"}' | carto maps update <map-id> --json
向现有地图添加一个数据集(合并模式保留现有数据集):
sh
carto maps get <map-id> --json > current.json
jq '.datasets += [{"$ref":"extra","type":"table","source":"proj.ds.new_table","connectionId":"<conn-id>","geoColumn":"geom","columns":["geom"],"format":"tilejson","label":"New source"}]' current.json > updated.json
carto maps update <map-id> --json < updated.json
替换所有数据集(破坏性操作——输入中未包含的数据集会被删除):
sh
carto maps update <map-id> --datasets-mode replace --json < map.json
更新单个数据集的源SQL(无
keplerMapConfig
清除风险):
sh
carto maps datasets update <map-id> <dataset-id> --source "SELECT geom, revenue FROM stores WHERE country = 'ES'"
更长的示例(完整JSON包)请参阅
references/examples.md

When in doubt

遇到疑问时

  • Field unknown / suspect?
    carto maps schema [section]
    returns the authoritative JSON Schema.
  • Map renders blank / wrong?
    references/troubleshooting.md
    symptom→fix table.
  • Visual sanity check?
    carto maps screenshot <id>
    — PNG render without leaving the terminal.
  • AI agent surfaces?
    carto maps agents status
    /
    models
    /
    mcp-tools
    /
    core-tools
    .
  • Stuck after a write? Tell the user to reload the Builder tab — Builder doesn't subscribe to server events.
  • 字段未知/可疑?
    carto maps schema [section]
    返回权威的JSON Schema。
  • 地图显示空白/异常?
    references/troubleshooting.md
    中的症状→解决方案对照表。
  • 视觉sanity检查?
    carto maps screenshot <id>
    — 无需离开终端的PNG渲染。
  • AI Agent相关?
    carto maps agents status
    /
    models
    /
    mcp-tools
    /
    core-tools
  • 写入后卡住? 告知用户重新加载Builder标签页——Builder不会订阅服务器事件。",