{
  "schemaVersion": "1.0",
  "item": {
    "slug": "openclaw-json-editing",
    "name": "OpenClaw JSON Editing Masterclass",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/avirweb/openclaw-json-editing",
    "canonicalUrl": "https://clawhub.ai/avirweb/openclaw-json-editing",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/openclaw-json-editing",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=openclaw-json-editing",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "SKILL.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/openclaw-json-editing"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/openclaw-json-editing",
    "agentPageUrl": "https://openagent3.xyz/skills/openclaw-json-editing/agent",
    "manifestUrl": "https://openagent3.xyz/skills/openclaw-json-editing/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/openclaw-json-editing/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "OpenClaw JSON Editing",
        "body": "Expert guidance for editing JSON in the OpenClaw ecosystem. OpenClaw uses JSON5 for configuration (allows comments, trailing commas), has sophisticated config merging, and validates with Zod schemas."
      },
      {
        "title": "Quick Reference",
        "body": "TaskCommand/PatternValidate configopenclaw config validateApply config patchopenclaw config patch <file.json>Safe JSON parseUse safeParseJson() wrapperCheck config locationopenclaw config pathPretty printJSON.stringify(data, null, 2)"
      },
      {
        "title": "OpenClaw JSON5 Config",
        "body": "OpenClaw config files use JSON5 (not strict JSON):\n\n{\n  // Single-line comments are allowed\n  \"gateway\": {\n    \"mode\": \"http\",  // Trailing commas are allowed\n  },\n  /* Multi-line comments\n     are also supported */\n  \"agents\": {\n    \"main\": {\n      \"model\": \"anthropic/claude-opus-4-6\",\n    },\n  },\n}"
      },
      {
        "title": "Key Differences from JSON",
        "body": "Comments: Single-line (//) and multi-line (/* */)\nTrailing commas: Allowed in arrays and objects\nUnquoted keys: { key: \"value\" } is valid\nSingle quotes: 'string' is valid"
      },
      {
        "title": "Config File Locations",
        "body": "TypePathUser config~/.openclaw/config.jsonProject config./openclaw.config.jsonAgent config~/.openclaw/agents/<id>/config.jsonSession store~/.openclaw/sessions/State dir~/.openclaw/ (or $OPENCLAW_STATE_DIR)"
      },
      {
        "title": "Reading Config Files",
        "body": "OpenClaw uses JSON5.parse() for configs and safe wrappers:\n\n// OpenClaw's safeParseJson pattern\nfunction safeParseJson<T>(raw: string): T | null {\n  try {\n    return JSON.parse(raw) as T;\n  } catch {\n    return null;\n  }\n}\n\n// For OpenClaw configs, use JSON5\nimport JSON5 from \"json5\";\n\nfunction loadConfigFile(path: string): unknown {\n  try {\n    const raw = fs.readFileSync(path, \"utf8\");\n    return JSON5.parse(raw);  // Allows comments, trailing commas\n  } catch {\n    return undefined;\n  }\n}"
      },
      {
        "title": "Writing Config Files",
        "body": "OpenClaw writes with specific formatting and permissions:\n\nfunction saveJsonFile(pathname: string, data: unknown) {\n  const dir = path.dirname(pathname);\n  if (!fs.existsSync(dir)) {\n    fs.mkdirSync(dir, { recursive: true, mode: 0o700 });\n  }\n  // 2-space indentation, trailing newline\n  fs.writeFileSync(pathname, `${JSON.stringify(data, null, 2)}\\n`, \"utf8\");\n  fs.chmodSync(pathname, 0o600);  // User read/write only\n}"
      },
      {
        "title": "Type Guards",
        "body": "Always validate before assuming structure:\n\n// OpenClaw's isPlainObject (strictest)\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n  return (\n    typeof value === \"object\" &&\n    value !== null &&\n    !Array.isArray(value) &&\n    Object.prototype.toString.call(value) === \"[object Object]\"\n  );\n}\n\n// Less strict version\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n  return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}"
      },
      {
        "title": "Merge Patch (RFC 7386)",
        "body": "OpenClaw uses merge patching for config updates:\n\n// Apply a merge patch to base config\nfunction applyMergePatch(base: unknown, patch: unknown): unknown {\n  if (!isPlainObject(patch)) {\n    return patch;\n  }\n\n  const result: Record<string, unknown> = isPlainObject(base) ? { ...base } : {};\n\n  for (const [key, value] of Object.entries(patch)) {\n    if (value === null) {\n      delete result[key];  // null = delete key\n      continue;\n    }\n    if (isPlainObject(value)) {\n      const baseValue = result[key];\n      result[key] = applyMergePatch(\n        isPlainObject(baseValue) ? baseValue : {},\n        value\n      );\n      continue;\n    }\n    result[key] = value;\n  }\n\n  return result;\n}"
      },
      {
        "title": "Usage Examples",
        "body": "// Add/update nested field\nconst patch = {\n  agents: {\n    main: {\n      model: \"anthropic/claude-opus-4-6\"\n    }\n  }\n};\n\n// Delete a field (set to null)\nconst deletePatch = {\n  agents: {\n    main: {\n      temperature: null  // Removes temperature\n    }\n  }\n};\n\n// Replace entire section\nconst replacePatch = {\n  channels: {\n    telegram: null,  // Delete old\n    discord: { token: \"new-token\" }  // Add new\n  }\n};"
      },
      {
        "title": "Environment Variable Substitution",
        "body": "OpenClaw configs support ${VAR} and ${VAR:-default} syntax:\n\n{\n  \"auth\": {\n    \"profiles\": {\n      \"openai\": {\n        \"apiKey\": \"${OPENAI_API_KEY}\"  // Substituted at load time\n      },\n      \"anthropic\": {\n        \"apiKey\": \"${ANTHROPIC_API_KEY:-fallback-key}\"\n      }\n    }\n  }\n}"
      },
      {
        "title": "Handling in Code",
        "body": "// Check if string contains env var reference\nfunction containsEnvVarReference(value: string): boolean {\n  return /\\$\\{[^}]+\\}/.test(value);\n}\n\n// Collect all env var paths in an object\nfunction collectEnvRefPaths(\n  value: unknown,\n  path: string,\n  output: Map<string, string>\n): void {\n  if (typeof value === \"string\") {\n    if (containsEnvVarReference(value)) {\n      output.set(path, value);\n    }\n    return;\n  }\n  if (Array.isArray(value)) {\n    value.forEach((item, index) => {\n      collectEnvRefPaths(item, `${path}[${index}]`, output);\n    });\n    return;\n  }\n  if (isPlainObject(value)) {\n    for (const [key, child] of Object.entries(value)) {\n      const childPath = path ? `${path}.${key}` : key;\n      collectEnvRefPaths(child, childPath, output);\n    }\n  }\n}"
      },
      {
        "title": "Zod Schema Pattern",
        "body": "OpenClaw uses Zod for runtime validation:\n\nimport { z } from \"zod\";\n\n// Define schema\nconst AgentConfigSchema = z.object({\n  model: z.string().optional(),\n  temperature: z.number().min(0).max(2).optional(),\n  maxTokens: z.number().positive().optional(),\n  enabled: z.boolean().default(true),\n});\n\n// Validate\ntype AgentConfig = z.infer<typeof AgentConfigSchema>;\n\nfunction validateConfig(data: unknown): AgentConfig {\n  return AgentConfigSchema.parse(data);\n}\n\n// Safe validation\nfunction safeValidateConfig(data: unknown): AgentConfig | null {\n  const result = AgentConfigSchema.safeParse(data);\n  return result.success ? result.data : null;\n}"
      },
      {
        "title": "Common OpenClaw Schema Types",
        "body": "// Model reference: \"provider/model-name\"\nconst ModelRefSchema = z.string().regex(/^[a-z0-9-]+\\/[a-z0-9-]+$/i);\n\n// Channel ID\nconst ChannelIdSchema = z.enum([\n  \"telegram\", \"discord\", \"slack\", \"whatsapp\",\n  \"signal\", \"imessage\", \"irc\", \"web\"\n]);\n\n// Duration string: \"30s\", \"5m\", \"1h\"\nconst DurationSchema = z.string().regex(/^\\d+[smhd]$/);"
      },
      {
        "title": "Config Includes",
        "body": "OpenClaw supports config file includes:\n\n{\n  \"include\": [\n    \"./base-config.json\",\n    \"~/.openclaw/shared-channels.json\"\n  ],\n  \"agents\": {\n    // Local overrides\n  }\n}"
      },
      {
        "title": "Processing Order",
        "body": "Load included files (recursive, depth-limited)\nMerge in order (later files override earlier)\nApply env var substitution\nValidate against schema\nApply runtime overrides"
      },
      {
        "title": "Common Operations",
        "body": "# Pretty print OpenClaw config\njq . ~/.openclaw/config.json\n\n# Get gateway mode\njq '.gateway.mode' ~/.openclaw/config.json\n\n# List all agent IDs\njq '.agents | keys[]' ~/.openclaw/config.json\n\n# Find agent using specific model\njq '.agents | to_entries[] | select(.value.model == \"anthropic/claude-opus-4-6\") | .key' ~/.openclaw/config.json\n\n# Get all channel types\njq '.channels | keys[]' ~/.openclaw/config.json\n\n# Check if Telegram is configured\njq '.channels.telegram != null' ~/.openclaw/config.json\n\n# Extract all model references\njq '.. | objects | select(has(\"model\")) | .model' ~/.openclaw/config.json\n\n# Merge patch using jq\njq '.agents.main.model = \"anthropic/claude-opus-4-6\"' ~/.openclaw/config.json > tmp.json \\\n  && mv tmp.json ~/.openclaw/config.json"
      },
      {
        "title": "Advanced jq",
        "body": "# Deep search for all API keys (for audit)\njq '.. | objects | .apiKey? // .token? // .password? | select(.)' ~/.openclaw/config.json\n\n# Collect all environment variable references\njq -r '.. | strings | select(contains(\"${\"))' ~/.openclaw/config.json\n\n# Validate JSON structure (returns true/false)\njq 'if has(\"gateway\") and has(\"agents\") then true else false end' ~/.openclaw/config.json\n\n# Create minimal config from full config\njq '{ gateway: .gateway, agents: { main: .agents.main } }' ~/.openclaw/config.json"
      },
      {
        "title": "Gateway Configuration",
        "body": "{\n  \"gateway\": {\n    \"mode\": \"http\",  // \"http\", \"disabled\", \"process\"\n    \"http\": {\n      \"bind\": \"127.0.0.1\",\n      \"port\": 3000,\n    },\n    \"auth\": {\n      \"token\": \"${OPENCLAW_GATEWAY_TOKEN}\",\n    },\n  },\n}"
      },
      {
        "title": "Agent Configuration",
        "body": "{\n  \"agents\": {\n    \"main\": {\n      \"model\": \"anthropic/claude-opus-4-6\",\n      \"temperature\": 0.7,\n      \"maxTokens\": 4096,\n      // System prompt or reference to file\n      \"systemPrompt\": \"You are a helpful assistant.\",\n      \"systemPromptFile\": \"~/.openclaw/agents/main/prompt.md\",\n    },\n    \"coder\": {\n      \"model\": \"anthropic/claude-sonnet-4-5\",\n      \"temperature\": 0.2,\n      // Inherit from main with overrides\n      \"inherits\": \"main\",\n    },\n  },\n}"
      },
      {
        "title": "Channel Configuration",
        "body": "{\n  \"channels\": {\n    \"telegram\": {\n      \"botToken\": \"${TELEGRAM_BOT_TOKEN}\",\n      \"allowFrom\": [\"@username\"],\n    },\n    \"discord\": {\n      \"botToken\": \"${DISCORD_BOT_TOKEN}\",\n      \"applicationId\": \"123456789\",\n    },\n    \"slack\": {\n      \"botToken\": \"${SLACK_BOT_TOKEN}\",\n      \"appToken\": \"${SLACK_APP_TOKEN}\",\n    },\n  },\n}"
      },
      {
        "title": "Tools Configuration",
        "body": "{\n  \"tools\": {\n    \"alsoAllow\": [\"web_search\", \"browser\"],\n    \"deny\": [\"exec\"],\n    \"config\": {\n      \"web_search\": {\n        \"provider\": \"brave\",\n        \"apiKey\": \"${BRAVE_API_KEY}\",\n      },\n    },\n  },\n}"
      },
      {
        "title": "Common Validation Errors",
        "body": "// Schema validation errors provide detailed paths\nconst result = schema.safeParse(data);\nif (!result.success) {\n  for (const error of result.error.errors) {\n    console.log(`${error.path.join('.')}: ${error.message}`);\n    // e.g., \"agents.main.temperature: Number must be less than or equal to 2\"\n  }\n}"
      },
      {
        "title": "Config File Recovery",
        "body": "# If config is corrupted, OpenClaw keeps backups\nls -la ~/.openclaw/config.json.*\n\n# Restore from backup\ncp ~/.openclaw/config.json.2024-01-15T10-30-00.bak ~/.openclaw/config.json\n\n# Or use OpenClaw's built-in rotation\nopenclaw config restore"
      },
      {
        "title": "1. Always Validate After Edit",
        "body": "# Validate config syntax and schema\nopenclaw config validate\n\n# Test config loading\nopenclaw config get"
      },
      {
        "title": "2. Backup Before Changes",
        "body": "# Create timestamped backup\ncp ~/.openclaw/config.json ~/.openclaw/config.json.$(date +%Y%m%d_%H%M%S).bak"
      },
      {
        "title": "3. Use Type Guards",
        "body": "// Never assume structure - always validate\nif (!isPlainObject(config.agents)) {\n  throw new Error(\"Invalid agents configuration\");\n}"
      },
      {
        "title": "4. Handle Env Vars Carefully",
        "body": "// Preserve env var references when editing\nconst originalValue = \"${API_KEY}\";\nconst newValue = process.env.API_KEY || originalValue;"
      },
      {
        "title": "5. Use Structured Clone for Deep Copies",
        "body": "// Preferred for deep cloning\ndeepCopy = structuredClone(original);\n\n// Fallback for older environments\ndeepCopy = JSON.parse(JSON.stringify(original));"
      },
      {
        "title": "6. Atomic Writes",
        "body": "// Write to temp file, then rename\nfs.writeFileSync(tempPath, data);\nfs.renameSync(tempPath, finalPath);"
      },
      {
        "title": "Security Considerations",
        "body": "File permissions: Config files should be 0o600 (user read/write only)\nNo secrets in JSON: Use ${ENV_VAR} substitution\nValidate inputs: Always schema-validate external JSON\nSanitize paths: Use path.resolve() and check traversal\nAudit logging: OpenClaw logs config changes to config-audit.jsonl"
      },
      {
        "title": "Common Issues",
        "body": "IssueCauseSolutionUnexpected token /Comments in JSONUse JSON5 parserTrailing commaTrailing comma in arrayUse JSON5 parserEnv var not substitutedMissing env varCheck ${VAR:-default}Validation failedSchema mismatchRun openclaw config validatePermission deniedWrong file permissionschmod 600 config.json"
      },
      {
        "title": "Debug Commands",
        "body": "# Check raw config (before env substitution)\ncat ~/.openclaw/config.json\n\n# Check effective config (after all processing)\nopenclaw config get --json\n\n# List all env var references\nopenclaw config env-refs\n\n# Trace config loading\nOPENCLAW_DEBUG=config openclaw config get"
      },
      {
        "title": "Editing Providers & Model Configuration",
        "body": "When adding or updating AI providers in openclaw.config.json, you must discover actual model names from the provider's API and handle reasoning model variants correctly."
      },
      {
        "title": "Model Discovery Workflow",
        "body": "# 1. Fetch available models from provider API\n# xAI example - requires XAI_API_KEY\nXAI_API_KEY=\"your-key\"\ncurl -s -H \"Authorization: Bearer $XAI_API_KEY\" \\\n  https://api.x.ai/v1/models | jq '.data[] | {id: .id, name: .object}'\n\n# OpenAI example\ncurl -s -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n  https://api.openai.com/v1/models | jq '.data[] | select(.id | contains(\"gpt\")) | .id'\n\n# Together AI example\ncurl -s -H \"Authorization: Bearer $TOGETHER_API_KEY\" \\\n  https://api.together.xyz/v1/models | jq '.[] | {id: .id, name: .display_name}'"
      },
      {
        "title": "Provider Configuration Schema",
        "body": "OpenClaw uses ModelProviderConfig schema:\n\ntype ModelProviderConfig = {\n  baseUrl: string;           // API endpoint base URL\n  apiKey?: string;           // Optional: API key (prefer env vars)\n  auth?: \"api-key\" | \"aws-sdk\" | \"oauth\" | \"token\";\n  api?: \"openai-completions\" | \"openai-responses\" | \n        \"anthropic-messages\" | \"google-generative-ai\" |\n        \"github-copilot\" | \"bedrock-converse-stream\" | \"ollama\";\n  headers?: Record<string, string>;  // Custom headers\n  models: ModelDefinitionConfig[];   // Model definitions\n};\n\ntype ModelDefinitionConfig = {\n  id: string;                // Model ID (e.g., \"grok-4\")\n  name: string;              // Display name (e.g., \"Grok 4\")\n  api?: ModelApi;            // Override API type per model\n  reasoning: boolean;        // Whether model supports reasoning/thinking\n  input: Array<\"text\" | \"image\">;  // Supported input types\n  cost: {\n    input: number;           // Cost per 1M input tokens\n    output: number;          // Cost per 1M output tokens\n    cacheRead: number;       // Cost per 1M cached tokens read\n    cacheWrite: number;      // Cost per 1M cached tokens written\n  };\n  contextWindow: number;     // Max context window size\n  maxTokens: number;         // Max output tokens\n  headers?: Record<string, string>;\n  compat?: ModelCompatConfig;\n};"
      },
      {
        "title": "Reasoning Model Families",
        "body": "CRITICAL: Some models have reasoning variants handled specially by OpenClaw. For example, xAI's grok-4-1-fast has three variants:\n\nModel IDTypeNotesgrok-4-1-fastBaseThe \"family\" identifiergrok-4-1-fast-reasoningReasoningFull reasoning capabilitiesgrok-4-1-fast-non-reasoningNon-reasoningFaster, no reasoning\n\nIn OpenClaw, you typically configure ONLY the base model (grok-4-1-fast). The system automatically switches between reasoning/non-reasoning variants based on the thinking directive or configuration.\n\n{\n  \"models\": {\n    \"providers\": {\n      \"xai\": {\n        \"baseUrl\": \"https://api.x.ai/v1\",\n        \"api\": \"openai-completions\",\n        \"apiKey\": \"${XAI_API_KEY}\",\n        \"models\": [\n          {\n            \"id\": \"grok-4-1-fast\",\n            \"name\": \"Grok 4.1 Fast\",\n            \"reasoning\": false,  // Base model is non-reasoning\n            \"input\": [\"text\"],\n            \"cost\": { \"input\": 0, \"output\": 0, \"cacheRead\": 0, \"cacheWrite\": 0 },\n            \"contextWindow\": 128000,\n            \"maxTokens\": 8192\n          }\n          // NOTE: Do NOT add -reasoning or -non-reasoning variants separately\n          // OpenClaw handles these automatically via model family resolution\n        ]\n      }\n    }\n  }\n}"
      },
      {
        "title": "Model Family Resolution",
        "body": "OpenClaw internally defines reasoning model families in src/agents/model-families.ts:\n\nconst REASONING_MODEL_FAMILIES = [\n  {\n    provider: \"xai\",\n    members: [\n      \"grok-4-1-fast\",\n      \"grok-4-1-fast-reasoning\",\n      \"grok-4-1-fast-non-reasoning\"\n    ],\n    reasoningModel: \"grok-4-1-fast-reasoning\",\n    nonReasoningModel: \"grok-4-1-fast-non-reasoning\",\n  },\n];\n\nWhen a user requests a model with thinking: \"on\" or thinking: \"off\", OpenClaw:\n\nLooks up if the requested model is in a reasoning family\nIf thinking: \"on\" → uses reasoningModel variant\nIf thinking: \"off\" → uses nonReasoningModel variant\nIf no thinking directive → uses the base model as-is"
      },
      {
        "title": "Complete Provider Configuration Example",
        "body": "{\n  \"models\": {\n    \"mode\": \"merge\",  // \"merge\" or \"replace\"\n    \"providers\": {\n      // xAI - Grok models with reasoning variants\n      \"xai\": {\n        \"baseUrl\": \"https://api.x.ai/v1\",\n        \"api\": \"openai-completions\",\n        \"apiKey\": \"${XAI_API_KEY}\",\n        \"models\": [\n          {\n            \"id\": \"grok-4-1-fast\",\n            \"name\": \"Grok 4.1 Fast\",\n            \"reasoning\": false,\n            \"input\": [\"text\"],\n            \"cost\": { \"input\": 0, \"output\": 0, \"cacheRead\": 0, \"cacheWrite\": 0 },\n            \"contextWindow\": 128000,\n            \"maxTokens\": 8192\n          },\n          {\n            \"id\": \"grok-4\",\n            \"name\": \"Grok 4\",\n            \"reasoning\": false,\n            \"input\": [\"text\", \"image\"],  // Vision-capable\n            \"cost\": { \"input\": 0, \"output\": 0, \"cacheRead\": 0, \"cacheWrite\": 0 },\n            \"contextWindow\": 128000,\n            \"maxTokens\": 8192,\n            \"compat\": {\n              \"supportsReasoningEffort\": false,\n              \"maxTokensField\": \"max_completion_tokens\"\n            }\n          }\n        ]\n      },\n      \n      // OpenAI - with response API and reasoning\n      \"openai\": {\n        \"baseUrl\": \"https://api.openai.com/v1\",\n        \"api\": \"openai-responses\",\n        \"apiKey\": \"${OPENAI_API_KEY}\",\n        \"models\": [\n          {\n            \"id\": \"gpt-5.2\",\n            \"name\": \"GPT-5.2\",\n            \"reasoning\": false,\n            \"input\": [\"text\", \"image\"],\n            \"cost\": { \"input\": 2.5, \"output\": 10, \"cacheRead\": 0.5, \"cacheWrite\": 1.25 },\n            \"contextWindow\": 200000,\n            \"maxTokens\": 16384,\n            \"compat\": {\n              \"supportsReasoningEffort\": true,\n              \"thinkingFormat\": \"openai\"\n            }\n          },\n          {\n            \"id\": \"o3-mini\",\n            \"name\": \"o3 Mini\",\n            \"reasoning\": true,  // Built-in reasoning model\n            \"input\": [\"text\", \"image\"],\n            \"cost\": { \"input\": 1.1, \"output\": 4.4, \"cacheRead\": 0.275, \"cacheWrite\": 0.55 },\n            \"contextWindow\": 200000,\n            \"maxTokens\": 100000,\n            \"compat\": {\n              \"supportsReasoningEffort\": true,\n              \"requiresAssistantAfterToolResult\": true\n            }\n          }\n        ]\n      },\n      \n      // Anthropic - Messages API\n      \"anthropic\": {\n        \"baseUrl\": \"https://api.anthropic.com\",\n        \"api\": \"anthropic-messages\",\n        \"apiKey\": \"${ANTHROPIC_API_KEY}\",\n        \"models\": [\n          {\n            \"id\": \"claude-opus-4-6\",\n            \"name\": \"Claude Opus 4.6\",\n            \"reasoning\": false,\n            \"input\": [\"text\", \"image\"],\n            \"cost\": { \"input\": 15, \"output\": 75, \"cacheRead\": 1.88, \"cacheWrite\": 7.5 },\n            \"contextWindow\": 200000,\n            \"maxTokens\": 8192,\n            \"compat\": {\n              \"supportsStore\": false,\n              \"supportsDeveloperRole\": false\n            }\n          }\n        ]\n      },\n      \n      // Google Gemini\n      \"google\": {\n        \"baseUrl\": \"https://generativelanguage.googleapis.com/v1beta\",\n        \"api\": \"google-generative-ai\",\n        \"apiKey\": \"${GEMINI_API_KEY}\",\n        \"models\": [\n          {\n            \"id\": \"gemini-3-pro-preview\",\n            \"name\": \"Gemini 3 Pro Preview\",\n            \"reasoning\": false,\n            \"input\": [\"text\", \"image\"],\n            \"cost\": { \"input\": 1.25, \"output\": 10, \"cacheRead\": 0.31, \"cacheWrite\": 1.25 },\n            \"contextWindow\": 1000000,\n            \"maxTokens\": 8192,\n            \"compat\": {\n              \"thinkingFormat\": \"qwen\"\n            }\n          }\n        ]\n      },\n      \n      // Ollama - local models (auto-discovered)\n      \"ollama\": {\n        \"baseUrl\": \"http://localhost:11434/v1\",\n        \"api\": \"ollama\",\n        \"models\": []  // Auto-populated from /api/tags\n      }\n    }\n  }\n}"
      },
      {
        "title": "Model Compatibility Flags",
        "body": "type ModelCompatConfig = {\n  // OpenAI-specific features\n  supportsStore?: boolean;                    // Use 'store' parameter\n  supportsDeveloperRole?: boolean;            // Use 'developer' vs 'system' role\n  supportsReasoningEffort?: boolean;          // Support reasoning_effort param\n  supportsUsageInStreaming?: boolean;         // Usage in streaming responses\n  supportsStrictMode?: boolean;               // Strict tool mode\n  \n  // Token handling\n  maxTokensField?: \"max_completion_tokens\" | \"max_tokens\";\n  \n  // Thinking/reasoning format\n  thinkingFormat?: \"openai\" | \"zai\" | \"qwen\";\n  \n  // Tool calling quirks\n  requiresToolResultName?: boolean;           // Must include tool result name\n  requiresAssistantAfterToolResult?: boolean; // Assistant message after tool\n  requiresThinkingAsText?: boolean;           // Thinking blocks as text\n  requiresMistralToolIds?: boolean;           // Mistral-style tool IDs\n};"
      },
      {
        "title": "Validating Provider Configuration",
        "body": "# Validate the full config including models\nopenclaw config validate\n\n# Check if models.json is correctly generated\nopenclaw models list\n\n# Test a specific model provider\nopenclaw models test --provider xai --model grok-4-1-fast\n\n# Debug model resolution\nOPENCLAW_DEBUG=models openclaw models list"
      },
      {
        "title": "Common Pitfalls",
        "body": "PitfallWhy It HappensSolutionAdding -reasoning variantsDon't manually add reasoning variantsOnly add base model (e.g., grok-4-1-fast)Wrong reasoning booleanConfusion about model capabilitiesSet based on base model, not variantsMissing api fieldDefaults may not match providerExplicitly set api to correct valueHardcoded API keysSecurity riskAlways use ${ENV_VAR} substitutionWrong baseUrlProvider-specific endpointsCheck provider documentationIncorrect cost valuesTracking/budgeting issuesVerify per-provider pricing"
      },
      {
        "title": "Provider-Specific Notes",
        "body": "xAI (Grok)\n\nUses openai-completions API\nModel families auto-resolve reasoning variants\nVision support varies by model\n\nOpenAI\n\nUse openai-responses for o-series and GPT-5\nUse openai-completions for legacy GPT-4\nReasoning effort adjustable via supportsReasoningEffort\n\nAnthropic\n\nUses anthropic-messages API\nNo separate reasoning models (all models can think)\nDistinct cost structure for prompt caching\n\nGoogle (Gemini)\n\nUses google-generative-ai API\nVery large context windows (1M tokens)\nDifferent content format than OpenAI/Anthropic\n\nOllama\n\nSet api: \"ollama\" for native discovery\nModels auto-discovered from /api/tags\nLocal inference - no API key needed"
      },
      {
        "title": "Model Aliases",
        "body": "Define aliases for common models in agent defaults:\n\n{\n  \"agents\": {\n    \"defaults\": {\n      \"models\": {\n        \"fast\": { \"alias\": \"Grok Fast\", \"id\": \"xai/grok-4-1-fast\" },\n        \"smart\": { \"alias\": \"Claude Opus\", \"id\": \"anthropic/claude-opus-4-6\" },\n        \"vision\": { \"alias\": \"GPT Vision\", \"id\": \"openai/gpt-5.2\" }\n      }\n    }\n  }\n}\n\nUse aliases in agent config:\n\n{\n  \"agents\": {\n    \"main\": {\n      \"model\": \"fast\"  // Resolves to xai/grok-4-1-fast\n    }\n  }\n}"
      }
    ],
    "body": "OpenClaw JSON Editing\n\nExpert guidance for editing JSON in the OpenClaw ecosystem. OpenClaw uses JSON5 for configuration (allows comments, trailing commas), has sophisticated config merging, and validates with Zod schemas.\n\nQuick Reference\nTask\tCommand/Pattern\nValidate config\topenclaw config validate\nApply config patch\topenclaw config patch <file.json>\nSafe JSON parse\tUse safeParseJson() wrapper\nCheck config location\topenclaw config path\nPretty print\tJSON.stringify(data, null, 2)\nOpenClaw JSON5 Config\n\nOpenClaw config files use JSON5 (not strict JSON):\n\n{\n  // Single-line comments are allowed\n  \"gateway\": {\n    \"mode\": \"http\",  // Trailing commas are allowed\n  },\n  /* Multi-line comments\n     are also supported */\n  \"agents\": {\n    \"main\": {\n      \"model\": \"anthropic/claude-opus-4-6\",\n    },\n  },\n}\n\nKey Differences from JSON\nComments: Single-line (//) and multi-line (/* */)\nTrailing commas: Allowed in arrays and objects\nUnquoted keys: { key: \"value\" } is valid\nSingle quotes: 'string' is valid\nConfig File Locations\nType\tPath\nUser config\t~/.openclaw/config.json\nProject config\t./openclaw.config.json\nAgent config\t~/.openclaw/agents/<id>/config.json\nSession store\t~/.openclaw/sessions/\nState dir\t~/.openclaw/ (or $OPENCLAW_STATE_DIR)\nSafe JSON Operations\nReading Config Files\n\nOpenClaw uses JSON5.parse() for configs and safe wrappers:\n\n// OpenClaw's safeParseJson pattern\nfunction safeParseJson<T>(raw: string): T | null {\n  try {\n    return JSON.parse(raw) as T;\n  } catch {\n    return null;\n  }\n}\n\n// For OpenClaw configs, use JSON5\nimport JSON5 from \"json5\";\n\nfunction loadConfigFile(path: string): unknown {\n  try {\n    const raw = fs.readFileSync(path, \"utf8\");\n    return JSON5.parse(raw);  // Allows comments, trailing commas\n  } catch {\n    return undefined;\n  }\n}\n\nWriting Config Files\n\nOpenClaw writes with specific formatting and permissions:\n\nfunction saveJsonFile(pathname: string, data: unknown) {\n  const dir = path.dirname(pathname);\n  if (!fs.existsSync(dir)) {\n    fs.mkdirSync(dir, { recursive: true, mode: 0o700 });\n  }\n  // 2-space indentation, trailing newline\n  fs.writeFileSync(pathname, `${JSON.stringify(data, null, 2)}\\n`, \"utf8\");\n  fs.chmodSync(pathname, 0o600);  // User read/write only\n}\n\nType Guards\n\nAlways validate before assuming structure:\n\n// OpenClaw's isPlainObject (strictest)\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n  return (\n    typeof value === \"object\" &&\n    value !== null &&\n    !Array.isArray(value) &&\n    Object.prototype.toString.call(value) === \"[object Object]\"\n  );\n}\n\n// Less strict version\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n  return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nConfig Merging & Patching\nMerge Patch (RFC 7386)\n\nOpenClaw uses merge patching for config updates:\n\n// Apply a merge patch to base config\nfunction applyMergePatch(base: unknown, patch: unknown): unknown {\n  if (!isPlainObject(patch)) {\n    return patch;\n  }\n\n  const result: Record<string, unknown> = isPlainObject(base) ? { ...base } : {};\n\n  for (const [key, value] of Object.entries(patch)) {\n    if (value === null) {\n      delete result[key];  // null = delete key\n      continue;\n    }\n    if (isPlainObject(value)) {\n      const baseValue = result[key];\n      result[key] = applyMergePatch(\n        isPlainObject(baseValue) ? baseValue : {},\n        value\n      );\n      continue;\n    }\n    result[key] = value;\n  }\n\n  return result;\n}\n\nUsage Examples\n// Add/update nested field\nconst patch = {\n  agents: {\n    main: {\n      model: \"anthropic/claude-opus-4-6\"\n    }\n  }\n};\n\n// Delete a field (set to null)\nconst deletePatch = {\n  agents: {\n    main: {\n      temperature: null  // Removes temperature\n    }\n  }\n};\n\n// Replace entire section\nconst replacePatch = {\n  channels: {\n    telegram: null,  // Delete old\n    discord: { token: \"new-token\" }  // Add new\n  }\n};\n\nEnvironment Variable Substitution\n\nOpenClaw configs support ${VAR} and ${VAR:-default} syntax:\n\n{\n  \"auth\": {\n    \"profiles\": {\n      \"openai\": {\n        \"apiKey\": \"${OPENAI_API_KEY}\"  // Substituted at load time\n      },\n      \"anthropic\": {\n        \"apiKey\": \"${ANTHROPIC_API_KEY:-fallback-key}\"\n      }\n    }\n  }\n}\n\nHandling in Code\n// Check if string contains env var reference\nfunction containsEnvVarReference(value: string): boolean {\n  return /\\$\\{[^}]+\\}/.test(value);\n}\n\n// Collect all env var paths in an object\nfunction collectEnvRefPaths(\n  value: unknown,\n  path: string,\n  output: Map<string, string>\n): void {\n  if (typeof value === \"string\") {\n    if (containsEnvVarReference(value)) {\n      output.set(path, value);\n    }\n    return;\n  }\n  if (Array.isArray(value)) {\n    value.forEach((item, index) => {\n      collectEnvRefPaths(item, `${path}[${index}]`, output);\n    });\n    return;\n  }\n  if (isPlainObject(value)) {\n    for (const [key, child] of Object.entries(value)) {\n      const childPath = path ? `${path}.${key}` : key;\n      collectEnvRefPaths(child, childPath, output);\n    }\n  }\n}\n\nSchema Validation\nZod Schema Pattern\n\nOpenClaw uses Zod for runtime validation:\n\nimport { z } from \"zod\";\n\n// Define schema\nconst AgentConfigSchema = z.object({\n  model: z.string().optional(),\n  temperature: z.number().min(0).max(2).optional(),\n  maxTokens: z.number().positive().optional(),\n  enabled: z.boolean().default(true),\n});\n\n// Validate\ntype AgentConfig = z.infer<typeof AgentConfigSchema>;\n\nfunction validateConfig(data: unknown): AgentConfig {\n  return AgentConfigSchema.parse(data);\n}\n\n// Safe validation\nfunction safeValidateConfig(data: unknown): AgentConfig | null {\n  const result = AgentConfigSchema.safeParse(data);\n  return result.success ? result.data : null;\n}\n\nCommon OpenClaw Schema Types\n// Model reference: \"provider/model-name\"\nconst ModelRefSchema = z.string().regex(/^[a-z0-9-]+\\/[a-z0-9-]+$/i);\n\n// Channel ID\nconst ChannelIdSchema = z.enum([\n  \"telegram\", \"discord\", \"slack\", \"whatsapp\",\n  \"signal\", \"imessage\", \"irc\", \"web\"\n]);\n\n// Duration string: \"30s\", \"5m\", \"1h\"\nconst DurationSchema = z.string().regex(/^\\d+[smhd]$/);\n\nConfig Includes\n\nOpenClaw supports config file includes:\n\n{\n  \"include\": [\n    \"./base-config.json\",\n    \"~/.openclaw/shared-channels.json\"\n  ],\n  \"agents\": {\n    // Local overrides\n  }\n}\n\nProcessing Order\nLoad included files (recursive, depth-limited)\nMerge in order (later files override earlier)\nApply env var substitution\nValidate against schema\nApply runtime overrides\njq Patterns for OpenClaw\nCommon Operations\n# Pretty print OpenClaw config\njq . ~/.openclaw/config.json\n\n# Get gateway mode\njq '.gateway.mode' ~/.openclaw/config.json\n\n# List all agent IDs\njq '.agents | keys[]' ~/.openclaw/config.json\n\n# Find agent using specific model\njq '.agents | to_entries[] | select(.value.model == \"anthropic/claude-opus-4-6\") | .key' ~/.openclaw/config.json\n\n# Get all channel types\njq '.channels | keys[]' ~/.openclaw/config.json\n\n# Check if Telegram is configured\njq '.channels.telegram != null' ~/.openclaw/config.json\n\n# Extract all model references\njq '.. | objects | select(has(\"model\")) | .model' ~/.openclaw/config.json\n\n# Merge patch using jq\njq '.agents.main.model = \"anthropic/claude-opus-4-6\"' ~/.openclaw/config.json > tmp.json \\\n  && mv tmp.json ~/.openclaw/config.json\n\nAdvanced jq\n# Deep search for all API keys (for audit)\njq '.. | objects | .apiKey? // .token? // .password? | select(.)' ~/.openclaw/config.json\n\n# Collect all environment variable references\njq -r '.. | strings | select(contains(\"${\"))' ~/.openclaw/config.json\n\n# Validate JSON structure (returns true/false)\njq 'if has(\"gateway\") and has(\"agents\") then true else false end' ~/.openclaw/config.json\n\n# Create minimal config from full config\njq '{ gateway: .gateway, agents: { main: .agents.main } }' ~/.openclaw/config.json\n\nCommon Config Patterns\nGateway Configuration\n{\n  \"gateway\": {\n    \"mode\": \"http\",  // \"http\", \"disabled\", \"process\"\n    \"http\": {\n      \"bind\": \"127.0.0.1\",\n      \"port\": 3000,\n    },\n    \"auth\": {\n      \"token\": \"${OPENCLAW_GATEWAY_TOKEN}\",\n    },\n  },\n}\n\nAgent Configuration\n{\n  \"agents\": {\n    \"main\": {\n      \"model\": \"anthropic/claude-opus-4-6\",\n      \"temperature\": 0.7,\n      \"maxTokens\": 4096,\n      // System prompt or reference to file\n      \"systemPrompt\": \"You are a helpful assistant.\",\n      \"systemPromptFile\": \"~/.openclaw/agents/main/prompt.md\",\n    },\n    \"coder\": {\n      \"model\": \"anthropic/claude-sonnet-4-5\",\n      \"temperature\": 0.2,\n      // Inherit from main with overrides\n      \"inherits\": \"main\",\n    },\n  },\n}\n\nChannel Configuration\n{\n  \"channels\": {\n    \"telegram\": {\n      \"botToken\": \"${TELEGRAM_BOT_TOKEN}\",\n      \"allowFrom\": [\"@username\"],\n    },\n    \"discord\": {\n      \"botToken\": \"${DISCORD_BOT_TOKEN}\",\n      \"applicationId\": \"123456789\",\n    },\n    \"slack\": {\n      \"botToken\": \"${SLACK_BOT_TOKEN}\",\n      \"appToken\": \"${SLACK_APP_TOKEN}\",\n    },\n  },\n}\n\nTools Configuration\n{\n  \"tools\": {\n    \"alsoAllow\": [\"web_search\", \"browser\"],\n    \"deny\": [\"exec\"],\n    \"config\": {\n      \"web_search\": {\n        \"provider\": \"brave\",\n        \"apiKey\": \"${BRAVE_API_KEY}\",\n      },\n    },\n  },\n}\n\nValidation & Error Handling\nCommon Validation Errors\n// Schema validation errors provide detailed paths\nconst result = schema.safeParse(data);\nif (!result.success) {\n  for (const error of result.error.errors) {\n    console.log(`${error.path.join('.')}: ${error.message}`);\n    // e.g., \"agents.main.temperature: Number must be less than or equal to 2\"\n  }\n}\n\nConfig File Recovery\n# If config is corrupted, OpenClaw keeps backups\nls -la ~/.openclaw/config.json.*\n\n# Restore from backup\ncp ~/.openclaw/config.json.2024-01-15T10-30-00.bak ~/.openclaw/config.json\n\n# Or use OpenClaw's built-in rotation\nopenclaw config restore\n\nBest Practices\n1. Always Validate After Edit\n# Validate config syntax and schema\nopenclaw config validate\n\n# Test config loading\nopenclaw config get\n\n2. Backup Before Changes\n# Create timestamped backup\ncp ~/.openclaw/config.json ~/.openclaw/config.json.$(date +%Y%m%d_%H%M%S).bak\n\n3. Use Type Guards\n// Never assume structure - always validate\nif (!isPlainObject(config.agents)) {\n  throw new Error(\"Invalid agents configuration\");\n}\n\n4. Handle Env Vars Carefully\n// Preserve env var references when editing\nconst originalValue = \"${API_KEY}\";\nconst newValue = process.env.API_KEY || originalValue;\n\n5. Use Structured Clone for Deep Copies\n// Preferred for deep cloning\ndeepCopy = structuredClone(original);\n\n// Fallback for older environments\ndeepCopy = JSON.parse(JSON.stringify(original));\n\n6. Atomic Writes\n// Write to temp file, then rename\nfs.writeFileSync(tempPath, data);\nfs.renameSync(tempPath, finalPath);\n\nSecurity Considerations\nFile permissions: Config files should be 0o600 (user read/write only)\nNo secrets in JSON: Use ${ENV_VAR} substitution\nValidate inputs: Always schema-validate external JSON\nSanitize paths: Use path.resolve() and check traversal\nAudit logging: OpenClaw logs config changes to config-audit.jsonl\nTroubleshooting\nCommon Issues\nIssue\tCause\tSolution\nUnexpected token /\tComments in JSON\tUse JSON5 parser\nTrailing comma\tTrailing comma in array\tUse JSON5 parser\nEnv var not substituted\tMissing env var\tCheck ${VAR:-default}\nValidation failed\tSchema mismatch\tRun openclaw config validate\nPermission denied\tWrong file permissions\tchmod 600 config.json\nDebug Commands\n# Check raw config (before env substitution)\ncat ~/.openclaw/config.json\n\n# Check effective config (after all processing)\nopenclaw config get --json\n\n# List all env var references\nopenclaw config env-refs\n\n# Trace config loading\nOPENCLAW_DEBUG=config openclaw config get\n\nEditing Providers & Model Configuration\n\nWhen adding or updating AI providers in openclaw.config.json, you must discover actual model names from the provider's API and handle reasoning model variants correctly.\n\nModel Discovery Workflow\n# 1. Fetch available models from provider API\n# xAI example - requires XAI_API_KEY\nXAI_API_KEY=\"your-key\"\ncurl -s -H \"Authorization: Bearer $XAI_API_KEY\" \\\n  https://api.x.ai/v1/models | jq '.data[] | {id: .id, name: .object}'\n\n# OpenAI example\ncurl -s -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n  https://api.openai.com/v1/models | jq '.data[] | select(.id | contains(\"gpt\")) | .id'\n\n# Together AI example\ncurl -s -H \"Authorization: Bearer $TOGETHER_API_KEY\" \\\n  https://api.together.xyz/v1/models | jq '.[] | {id: .id, name: .display_name}'\n\nProvider Configuration Schema\n\nOpenClaw uses ModelProviderConfig schema:\n\ntype ModelProviderConfig = {\n  baseUrl: string;           // API endpoint base URL\n  apiKey?: string;           // Optional: API key (prefer env vars)\n  auth?: \"api-key\" | \"aws-sdk\" | \"oauth\" | \"token\";\n  api?: \"openai-completions\" | \"openai-responses\" | \n        \"anthropic-messages\" | \"google-generative-ai\" |\n        \"github-copilot\" | \"bedrock-converse-stream\" | \"ollama\";\n  headers?: Record<string, string>;  // Custom headers\n  models: ModelDefinitionConfig[];   // Model definitions\n};\n\ntype ModelDefinitionConfig = {\n  id: string;                // Model ID (e.g., \"grok-4\")\n  name: string;              // Display name (e.g., \"Grok 4\")\n  api?: ModelApi;            // Override API type per model\n  reasoning: boolean;        // Whether model supports reasoning/thinking\n  input: Array<\"text\" | \"image\">;  // Supported input types\n  cost: {\n    input: number;           // Cost per 1M input tokens\n    output: number;          // Cost per 1M output tokens\n    cacheRead: number;       // Cost per 1M cached tokens read\n    cacheWrite: number;      // Cost per 1M cached tokens written\n  };\n  contextWindow: number;     // Max context window size\n  maxTokens: number;         // Max output tokens\n  headers?: Record<string, string>;\n  compat?: ModelCompatConfig;\n};\n\nReasoning Model Families\n\nCRITICAL: Some models have reasoning variants handled specially by OpenClaw. For example, xAI's grok-4-1-fast has three variants:\n\nModel ID\tType\tNotes\ngrok-4-1-fast\tBase\tThe \"family\" identifier\ngrok-4-1-fast-reasoning\tReasoning\tFull reasoning capabilities\ngrok-4-1-fast-non-reasoning\tNon-reasoning\tFaster, no reasoning\n\nIn OpenClaw, you typically configure ONLY the base model (grok-4-1-fast). The system automatically switches between reasoning/non-reasoning variants based on the thinking directive or configuration.\n\n{\n  \"models\": {\n    \"providers\": {\n      \"xai\": {\n        \"baseUrl\": \"https://api.x.ai/v1\",\n        \"api\": \"openai-completions\",\n        \"apiKey\": \"${XAI_API_KEY}\",\n        \"models\": [\n          {\n            \"id\": \"grok-4-1-fast\",\n            \"name\": \"Grok 4.1 Fast\",\n            \"reasoning\": false,  // Base model is non-reasoning\n            \"input\": [\"text\"],\n            \"cost\": { \"input\": 0, \"output\": 0, \"cacheRead\": 0, \"cacheWrite\": 0 },\n            \"contextWindow\": 128000,\n            \"maxTokens\": 8192\n          }\n          // NOTE: Do NOT add -reasoning or -non-reasoning variants separately\n          // OpenClaw handles these automatically via model family resolution\n        ]\n      }\n    }\n  }\n}\n\nModel Family Resolution\n\nOpenClaw internally defines reasoning model families in src/agents/model-families.ts:\n\nconst REASONING_MODEL_FAMILIES = [\n  {\n    provider: \"xai\",\n    members: [\n      \"grok-4-1-fast\",\n      \"grok-4-1-fast-reasoning\",\n      \"grok-4-1-fast-non-reasoning\"\n    ],\n    reasoningModel: \"grok-4-1-fast-reasoning\",\n    nonReasoningModel: \"grok-4-1-fast-non-reasoning\",\n  },\n];\n\n\nWhen a user requests a model with thinking: \"on\" or thinking: \"off\", OpenClaw:\n\nLooks up if the requested model is in a reasoning family\nIf thinking: \"on\" → uses reasoningModel variant\nIf thinking: \"off\" → uses nonReasoningModel variant\nIf no thinking directive → uses the base model as-is\nComplete Provider Configuration Example\n{\n  \"models\": {\n    \"mode\": \"merge\",  // \"merge\" or \"replace\"\n    \"providers\": {\n      // xAI - Grok models with reasoning variants\n      \"xai\": {\n        \"baseUrl\": \"https://api.x.ai/v1\",\n        \"api\": \"openai-completions\",\n        \"apiKey\": \"${XAI_API_KEY}\",\n        \"models\": [\n          {\n            \"id\": \"grok-4-1-fast\",\n            \"name\": \"Grok 4.1 Fast\",\n            \"reasoning\": false,\n            \"input\": [\"text\"],\n            \"cost\": { \"input\": 0, \"output\": 0, \"cacheRead\": 0, \"cacheWrite\": 0 },\n            \"contextWindow\": 128000,\n            \"maxTokens\": 8192\n          },\n          {\n            \"id\": \"grok-4\",\n            \"name\": \"Grok 4\",\n            \"reasoning\": false,\n            \"input\": [\"text\", \"image\"],  // Vision-capable\n            \"cost\": { \"input\": 0, \"output\": 0, \"cacheRead\": 0, \"cacheWrite\": 0 },\n            \"contextWindow\": 128000,\n            \"maxTokens\": 8192,\n            \"compat\": {\n              \"supportsReasoningEffort\": false,\n              \"maxTokensField\": \"max_completion_tokens\"\n            }\n          }\n        ]\n      },\n      \n      // OpenAI - with response API and reasoning\n      \"openai\": {\n        \"baseUrl\": \"https://api.openai.com/v1\",\n        \"api\": \"openai-responses\",\n        \"apiKey\": \"${OPENAI_API_KEY}\",\n        \"models\": [\n          {\n            \"id\": \"gpt-5.2\",\n            \"name\": \"GPT-5.2\",\n            \"reasoning\": false,\n            \"input\": [\"text\", \"image\"],\n            \"cost\": { \"input\": 2.5, \"output\": 10, \"cacheRead\": 0.5, \"cacheWrite\": 1.25 },\n            \"contextWindow\": 200000,\n            \"maxTokens\": 16384,\n            \"compat\": {\n              \"supportsReasoningEffort\": true,\n              \"thinkingFormat\": \"openai\"\n            }\n          },\n          {\n            \"id\": \"o3-mini\",\n            \"name\": \"o3 Mini\",\n            \"reasoning\": true,  // Built-in reasoning model\n            \"input\": [\"text\", \"image\"],\n            \"cost\": { \"input\": 1.1, \"output\": 4.4, \"cacheRead\": 0.275, \"cacheWrite\": 0.55 },\n            \"contextWindow\": 200000,\n            \"maxTokens\": 100000,\n            \"compat\": {\n              \"supportsReasoningEffort\": true,\n              \"requiresAssistantAfterToolResult\": true\n            }\n          }\n        ]\n      },\n      \n      // Anthropic - Messages API\n      \"anthropic\": {\n        \"baseUrl\": \"https://api.anthropic.com\",\n        \"api\": \"anthropic-messages\",\n        \"apiKey\": \"${ANTHROPIC_API_KEY}\",\n        \"models\": [\n          {\n            \"id\": \"claude-opus-4-6\",\n            \"name\": \"Claude Opus 4.6\",\n            \"reasoning\": false,\n            \"input\": [\"text\", \"image\"],\n            \"cost\": { \"input\": 15, \"output\": 75, \"cacheRead\": 1.88, \"cacheWrite\": 7.5 },\n            \"contextWindow\": 200000,\n            \"maxTokens\": 8192,\n            \"compat\": {\n              \"supportsStore\": false,\n              \"supportsDeveloperRole\": false\n            }\n          }\n        ]\n      },\n      \n      // Google Gemini\n      \"google\": {\n        \"baseUrl\": \"https://generativelanguage.googleapis.com/v1beta\",\n        \"api\": \"google-generative-ai\",\n        \"apiKey\": \"${GEMINI_API_KEY}\",\n        \"models\": [\n          {\n            \"id\": \"gemini-3-pro-preview\",\n            \"name\": \"Gemini 3 Pro Preview\",\n            \"reasoning\": false,\n            \"input\": [\"text\", \"image\"],\n            \"cost\": { \"input\": 1.25, \"output\": 10, \"cacheRead\": 0.31, \"cacheWrite\": 1.25 },\n            \"contextWindow\": 1000000,\n            \"maxTokens\": 8192,\n            \"compat\": {\n              \"thinkingFormat\": \"qwen\"\n            }\n          }\n        ]\n      },\n      \n      // Ollama - local models (auto-discovered)\n      \"ollama\": {\n        \"baseUrl\": \"http://localhost:11434/v1\",\n        \"api\": \"ollama\",\n        \"models\": []  // Auto-populated from /api/tags\n      }\n    }\n  }\n}\n\nModel Compatibility Flags\ntype ModelCompatConfig = {\n  // OpenAI-specific features\n  supportsStore?: boolean;                    // Use 'store' parameter\n  supportsDeveloperRole?: boolean;            // Use 'developer' vs 'system' role\n  supportsReasoningEffort?: boolean;          // Support reasoning_effort param\n  supportsUsageInStreaming?: boolean;         // Usage in streaming responses\n  supportsStrictMode?: boolean;               // Strict tool mode\n  \n  // Token handling\n  maxTokensField?: \"max_completion_tokens\" | \"max_tokens\";\n  \n  // Thinking/reasoning format\n  thinkingFormat?: \"openai\" | \"zai\" | \"qwen\";\n  \n  // Tool calling quirks\n  requiresToolResultName?: boolean;           // Must include tool result name\n  requiresAssistantAfterToolResult?: boolean; // Assistant message after tool\n  requiresThinkingAsText?: boolean;           // Thinking blocks as text\n  requiresMistralToolIds?: boolean;           // Mistral-style tool IDs\n};\n\nValidating Provider Configuration\n# Validate the full config including models\nopenclaw config validate\n\n# Check if models.json is correctly generated\nopenclaw models list\n\n# Test a specific model provider\nopenclaw models test --provider xai --model grok-4-1-fast\n\n# Debug model resolution\nOPENCLAW_DEBUG=models openclaw models list\n\nCommon Pitfalls\nPitfall\tWhy It Happens\tSolution\nAdding -reasoning variants\tDon't manually add reasoning variants\tOnly add base model (e.g., grok-4-1-fast)\nWrong reasoning boolean\tConfusion about model capabilities\tSet based on base model, not variants\nMissing api field\tDefaults may not match provider\tExplicitly set api to correct value\nHardcoded API keys\tSecurity risk\tAlways use ${ENV_VAR} substitution\nWrong baseUrl\tProvider-specific endpoints\tCheck provider documentation\nIncorrect cost values\tTracking/budgeting issues\tVerify per-provider pricing\nProvider-Specific Notes\nxAI (Grok)\nUses openai-completions API\nModel families auto-resolve reasoning variants\nVision support varies by model\nOpenAI\nUse openai-responses for o-series and GPT-5\nUse openai-completions for legacy GPT-4\nReasoning effort adjustable via supportsReasoningEffort\nAnthropic\nUses anthropic-messages API\nNo separate reasoning models (all models can think)\nDistinct cost structure for prompt caching\nGoogle (Gemini)\nUses google-generative-ai API\nVery large context windows (1M tokens)\nDifferent content format than OpenAI/Anthropic\nOllama\nSet api: \"ollama\" for native discovery\nModels auto-discovered from /api/tags\nLocal inference - no API key needed\nModel Aliases\n\nDefine aliases for common models in agent defaults:\n\n{\n  \"agents\": {\n    \"defaults\": {\n      \"models\": {\n        \"fast\": { \"alias\": \"Grok Fast\", \"id\": \"xai/grok-4-1-fast\" },\n        \"smart\": { \"alias\": \"Claude Opus\", \"id\": \"anthropic/claude-opus-4-6\" },\n        \"vision\": { \"alias\": \"GPT Vision\", \"id\": \"openai/gpt-5.2\" }\n      }\n    }\n  }\n}\n\n\nUse aliases in agent config:\n\n{\n  \"agents\": {\n    \"main\": {\n      \"model\": \"fast\"  // Resolves to xai/grok-4-1-fast\n    }\n  }\n}"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/avirweb/openclaw-json-editing",
    "publisherUrl": "https://clawhub.ai/avirweb/openclaw-json-editing",
    "owner": "avirweb",
    "version": "1.0.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/openclaw-json-editing",
    "downloadUrl": "https://openagent3.xyz/downloads/openclaw-json-editing",
    "agentUrl": "https://openagent3.xyz/skills/openclaw-json-editing/agent",
    "manifestUrl": "https://openagent3.xyz/skills/openclaw-json-editing/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/openclaw-json-editing/agent.md"
  }
}