{
  "source_file": "0930",
  "source_platform": "Ghost",
  "author": "Avi Chawla / Daily Dose of Data Science",
  "title_listed": "Run Any Agent Harness Under One Interface",
  "keywords": "",
  "domain": "大模型算法",
  "content_type": "深度技术解析",
  "is_paid_flag": "否",
  "url": "https://www.dailydoseofds.com/p/run-any-agent-harness-under-one-interface/",
  "publish_date": "2026-09-28",
  "corpus_stage": "",
  "notes": "",
  "id": "c067df749b61",
  "collected_at": "2026-10-02T13:41:29",
  "title": "Run any agent harness under one interface",
  "body_markdown": "[ Skip to main content  ](https://www.dailydoseofds.com/p/run-any-agent-harness-under-one-interface/#sx-main)\n[ ![Daily Dose of Data Science](https://storage.ghost.io/c/3f/df/3fdf6ed2-17ac-4b12-a693-8078bd13e748/content/images/2025/12/dailyds-logo-transparent-1.png) ](https://www.dailydoseofds.com)\n  * [ Newsletter ](https://dailydoseofds.github.io/ai-engg-book/)\n  * [ Archive ](https://www.dailydoseofds.com/archive/)\n  * Guidebooks \n    * [ MCP Guidebook ](https://www.dailydoseofds.com/what-is-mcp/)\n[ Agents Guidebook ](https://drive.google.com/file/d/1Th8mN_IF7Ttc8bI_OLtUuQ7Mjx3aJ6Hi/view)\n[ AI Engineering Guidebook ](https://drive.google.com/file/d/1_s2UaD7tEPECjgC5YMOa1LIOB9HUWFO-/view)\n[ DS Guidebook ](https://drive.google.com/file/d/1ZunUHwkD2Ut0_LrgDTDmlQRQkfT2lkVf/view)\n[ Courses ](https://www.dailydoseofds.com/)\n[ MLOps/LLMOps Course ](https://www.dailydoseofds.com/mlops-crash-course-part-1/)\n[ Reinforcement Learning Course ](https://www.dailydoseofds.com/rl-course-part-1/)\n[ AI Agents Course ](https://www.dailydoseofds.com/ai-agents-crash-course-part-1-with-implementation/)\n[ MCP Course ](https://www.dailydoseofds.com/model-context-protocol-crash-course-part-1/)\n[ RAG Systems Course ](https://www.dailydoseofds.com/a-crash-course-on-building-rag-systems-part-1-with-implementations/)\n  * Courses \n    * [ MLOps/LLMOps Course ](https://www.dailydoseofds.com/mlops-crash-course-part-1/)\n[ Reinforcement Learning Course ](https://www.dailydoseofds.com/rl-course-part-1/)\n[ AI Agents Course ](https://www.dailydoseofds.com/ai-agents-crash-course-part-1-with-implementation/)\n[ MCP Course ](https://www.dailydoseofds.com/model-context-protocol-crash-course-part-1/)\n[ RAG Systems Course ](https://www.dailydoseofds.com/a-crash-course-on-building-rag-systems-part-1-with-implementations/)\n[ LLM and Fine-tuning ](https://www.dailydoseofds.com/bi-encoders-and-cross-encoders-for-sentence-pair-similarity-scoring-part-1/)\n[ Classical ML and Deep Learning ](https://www.dailydoseofds.com/where-did-the-assumptions-of-linear-regression-originate-from/)\n[ Engineering Best Practices ](https://www.dailydoseofds.com/8-fatal-yet-non-obvious-pitfalls-and-cautionary-measures-in-data-science/)\n  *     * [ Newsletter ](https://dailydoseofds.github.io/ai-engg-book/)\n[ Archive ](https://www.dailydoseofds.com/archive/)\nGuidebooks \n      * [ MCP Guidebook ](https://www.dailydoseofds.com/what-is-mcp/)\n      * [ Agents Guidebook ](https://drive.google.com/file/d/1Th8mN_IF7Ttc8bI_OLtUuQ7Mjx3aJ6Hi/view)\n      * [ AI Engineering Guidebook ](https://drive.google.com/file/d/1_s2UaD7tEPECjgC5YMOa1LIOB9HUWFO-/view)\n      * [ DS Guidebook ](https://drive.google.com/file/d/1ZunUHwkD2Ut0_LrgDTDmlQRQkfT2lkVf/view)\n      * [ Courses ](https://www.dailydoseofds.com/)\n      * [ MLOps/LLMOps Course ](https://www.dailydoseofds.com/mlops-crash-course-part-1/)\n      * [ Reinforcement Learning Course ](https://www.dailydoseofds.com/rl-course-part-1/)\n      * [ AI Agents Course ](https://www.dailydoseofds.com/ai-agents-crash-course-part-1-with-implementation/)\n      * [ MCP Course ](https://www.dailydoseofds.com/model-context-protocol-crash-course-part-1/)\n      * [ RAG Systems Course ](https://www.dailydoseofds.com/a-crash-course-on-building-rag-systems-part-1-with-implementations/)\nCourses \n      * [ MLOps/LLMOps Course ](https://www.dailydoseofds.com/mlops-crash-course-part-1/)\n      * [ Reinforcement Learning Course ](https://www.dailydoseofds.com/rl-course-part-1/)\n      * [ AI Agents Course ](https://www.dailydoseofds.com/ai-agents-crash-course-part-1-with-implementation/)\n      * [ MCP Course ](https://www.dailydoseofds.com/model-context-protocol-crash-course-part-1/)\n      * [ RAG Systems Course ](https://www.dailydoseofds.com/a-crash-course-on-building-rag-systems-part-1-with-implementations/)\n      * [ LLM and Fine-tuning ](https://www.dailydoseofds.com/bi-encoders-and-cross-encoders-for-sentence-pair-similarity-scoring-part-1/)\n      * [ Classical ML and Deep Learning ](https://www.dailydoseofds.com/where-did-the-assumptions-of-linear-regression-originate-from/)\n      * [ Engineering Best Practices ](https://www.dailydoseofds.com/8-fatal-yet-non-obvious-pitfalls-and-cautionary-measures-in-data-science/)\n\n\nSign In  [ Get Started ](https://www.dailydoseofds.com/membership)\n/\n  * [ Newsletter ](https://dailydoseofds.github.io/ai-engg-book/)\n  * [ Archive ](https://www.dailydoseofds.com/archive/)\n  * Guidebooks \n    * [ MCP Guidebook ](https://www.dailydoseofds.com/what-is-mcp/)\n    * [ Agents Guidebook ](https://drive.google.com/file/d/1Th8mN_IF7Ttc8bI_OLtUuQ7Mjx3aJ6Hi/view)\n    * [ AI Engineering Guidebook ](https://drive.google.com/file/d/1_s2UaD7tEPECjgC5YMOa1LIOB9HUWFO-/view)\n    * [ DS Guidebook ](https://drive.google.com/file/d/1ZunUHwkD2Ut0_LrgDTDmlQRQkfT2lkVf/view)\n    * [ Courses ](https://www.dailydoseofds.com/)\n    * [ MLOps/LLMOps Course ](https://www.dailydoseofds.com/mlops-crash-course-part-1/)\n    * [ Reinforcement Learning Course ](https://www.dailydoseofds.com/rl-course-part-1/)\n    * [ AI Agents Course ](https://www.dailydoseofds.com/ai-agents-crash-course-part-1-with-implementation/)\n    * [ MCP Course ](https://www.dailydoseofds.com/model-context-protocol-crash-course-part-1/)\n    * [ RAG Systems Course ](https://www.dailydoseofds.com/a-crash-course-on-building-rag-systems-part-1-with-implementations/)\n  * Courses \n    * [ MLOps/LLMOps Course ](https://www.dailydoseofds.com/mlops-crash-course-part-1/)\n    * [ Reinforcement Learning Course ](https://www.dailydoseofds.com/rl-course-part-1/)\n    * [ AI Agents Course ](https://www.dailydoseofds.com/ai-agents-crash-course-part-1-with-implementation/)\n    * [ MCP Course ](https://www.dailydoseofds.com/model-context-protocol-crash-course-part-1/)\n    * [ RAG Systems Course ](https://www.dailydoseofds.com/a-crash-course-on-building-rag-systems-part-1-with-implementations/)\n    * [ LLM and Fine-tuning ](https://www.dailydoseofds.com/bi-encoders-and-cross-encoders-for-sentence-pair-similarity-scoring-part-1/)\n    * [ Classical ML and Deep Learning ](https://www.dailydoseofds.com/where-did-the-assumptions-of-linear-regression-originate-from/)\n    * [ Engineering Best Practices ](https://www.dailydoseofds.com/8-fatal-yet-non-obvious-pitfalls-and-cautionary-measures-in-data-science/)\n  * Sign In \n\n\nSep 23, 2026  Agent Harness \n#  Run any agent harness under one interface \nHow UHP and HarnessRouter standardize agent execution across Codex, Claude Code, Hermes, and other runtimes. \n![Avi Chawla](../images/000.jpg)\nAvi Chawla \n👉\n* * *\nWhen an agent product integrates one harness directly, its backend starts depending on that harness’s task format, event stream, session model, and filesystem behavior.\nUnlike model routing, adding another harness is not a config/parameter change because it adds another runtime that plans work, calls tools, manages files, and decides when a task is complete.\n![](../images/001.jpeg)\nAnd supporting more than one runtime is critical since harnesses are built differently.\nThe right choice can depend on the task, required tools, provider access, available models, cost, latency, or usage limits. Like models, a product should be able to add or replace a harness without rebuilding the feature around it.\nModel routing does not solve that problem. It chooses which model handles an inference request, while the same agent loop remains in place. Harness routing chooses the agent runtime that owns the complete task.\n![](../images/002.jpeg)\nToday, let’s talk about the engineering behind that second form of routing. We will understand why products may need different harnesses, what must be standardized across them, and how the [**Unified Harness Protocol**](https://github.com/HarnessRouter/harnessrouter?ref=dailydoseofds.com) defines that contract.\nWe will then use [**HarnessRouter**](https://github.com/HarnessRouter/harnessrouter?ref=dailydoseofds.com), an open-source UHP implementation, to run the same workflow through Codex and Claude Code.\n![](../images/003.png)\n#### Why a product may need another harness\nHarnesses make different choices about tool execution, context management, permissions, skills, and supported models. The same harness may not provide the right tools or model support for every product feature.\n![](../images/004.jpeg)\nA product may also serve customers with different provider access. One customer may already use OpenAI models, while another is set up around Anthropic. A quota or provider outage can also make one backend unavailable.\n![](../images/005.jpeg)\nEvaluation is another reason. Running the same task through two harnesses makes their cost, latency, tool use, and output easier to compare. The comparison is difficult when each backend requires different task and event code.\nThe goal is not to switch harnesses during every session but rather to keep the product from depending on one runtime.\n![](../images/006.jpeg)\nA team can select a harness per feature, offer a supported choice to customers, or replace a backend without changing the product workflow.\n#### A model call does not run the whole task\nA model API accepts input and returns generated output. The application still runs requested tools, starts follow-up model calls, and manages files, permissions, retries, and task state.\n![](../images/007.jpeg)\nAn agent harness includes this control loop. It can inspect files, call tools, edit a project, run commands, review the output, and decide when to stop.\nCodex and Claude Code can use similar models and still behave differently. Their instructions, tools, context handling, permissions, and completion rules affect the run.\n#### Model routing vs. harness routing\nModel routing happens inside the inference layer. It chooses an endpoint based on price, latency, context length, availability, or measured quality. The application or harness still owns the agent loop.\nHarness routing selects the runtime that owns the task. That choice can change the tools, skills, workspace, permissions, and event stream.\n![](../images/008.jpeg)\nA product may use both routing layers. In UHP, `model` chooses the model, while `metadata.harness_id` chooses the configured harness.\n#### What the product must handle for each harness\nThe first integration often starts as a small adapter that launches a process and reads its output. A product UI also needs live progress, session continuity, file uploads, download links, and access rules.\n![](../images/009.jpeg)\nCancellation needs a defined path because local processes, remote jobs, and sessions stop differently. Errors also need enough structure to separate provider failures, permission denials, time limits, missing files, and cancelled tasks.\nAdding Claude Code beside Codex means building and maintaining these mappings again. The product needs one task lifecycle that both integrations can follow.\n#### The task lifecycle defined by UHP\nThe Unified Harness Protocol defines the HTTP contract between an application and a harness server. It covers task creation, progress, sessions, files, cancellation, and errors without defining how the harness plans.\n![](../images/010.jpeg)\nUHP uses an API shaped like the OpenAI Responses API. A client starts work through `POST /v1/responses`. The request includes the task input, model, configured Harness ID, and optional execution limits.\nA response records one task. A session groups related responses that share conversation state and a working directory. A configured harness combines a base harness with its model, instructions, skills, tools, MCP servers, and limits.\n![](../images/011.jpeg)\nLive tasks use Server-Sent Events, or SSE. Each event has a type and sequence number, so the client can process the stream in order.\nThe events report text output, tool activity, files, and task status. The application displays them without searching raw terminal lines for each event.\nUHP accepts small files in the request and larger files through uploads. Generated files become artifacts that the application can list and download. The files specification defines those operations.\nFollow-up tasks use `previous_response_id`. The server continues the same session with its conversation, working directory, files, and configured harness.\nYou can still hand off work to another harness. If Codex starts a task and you want Claude Code to take over, start a new session with Claude Code and pass it the relevant context, such as a summary of the work so far, the next instructions, and any files it needs. Think of it as handing a task to another developer: the work can continue, but Claude Code is not resuming Codex’s session.\n![](../images/012.jpeg)\nFor comparison, the application starts two sessions and gives both the same PDF and prompt. Each harness receives clear input instead of hidden state created by another runtime. The session specification documents this rule.\nThe current UHP version is `2026-09-12`. The project publishes the written specification, OpenAPI 3.1 schema, JSON Schema definitions, and runnable conformance checks.\n#### How HarnessRouter runs a task\nHarnessRouter ([**GitHub Repo**](https://github.com/HarnessRouter/harnessrouter?ref=dailydoseofds.com)) is a self-hosted UHP server. It receives a UHP request, reads the Harness ID, and starts the selected runtime. As the harness works, HarnessRouter records its output as UHP events, responses, sessions, files, and errors.\nThe Docker image contains three services.\nThe Console provides the browser UI. The Gateway handles the UHP API and harness configuration. The Runner starts harness processes inside session workspaces.\nA named `/data` volume stores the database, installed harness CLIs, provider integrations, session files, and workspaces. Only the Console port is published. The Gateway and Runner listen on loopback inside the container.\n![](../images/013.jpeg)\nThe self-hosting guide lists Codex, Claude Code, Hermes, DeepSeek Harness, Gemini CLI, OpenCode, Qwen Code, Cline, Goose, and other backends.\nA built-in harness can run without a custom configuration. A custom harness starts with one base harness and adds a default model, instructions, tools, skills, and optional MCP servers. HarnessRouter gives the saved configuration a Harness ID.\n![](../images/014.jpeg)\nThe product sends this ID with each new task. It does not need to launch the harness CLI or parse the harness output itself.\n#### Running HarnessRouter locally\nCommunity Edition requires Docker, about 4 GB of disk, and an API key for a supported model provider.\nStart the container.\n\n```\ndocker run -d --name harnessrouter \\\n  -p 127.0.0.1:3000:3000 \\\n  -v harnessrouter:/data \\\n  harnessrouter/harnessrouter\n```\n\nThe `127.0.0.1` binding keeps the Console on the local machine. The named volume preserves its data across container restarts.\nFollow the startup logs.\n\n```\ndocker logs -f harnessrouter\n```\n\nThe first run installs the enabled harness CLIs:\n![](../images/015.png)\nWait for this message:\n![](../images/016.png)\n```\n[harnessrouter] ready on :3000\n```\n\nOpen `http://localhost:3000`.\n![](../images/017.png)The default username and password are both `harnessrouter`.\nNext, open **Integrations** in the left panel and select **Add Integration**. Choose a model provider and enter its API key:\n![](../images/018.png)\nThis key authorizes model requests. It is separate from the Console password and the API key later used by the application.\n![](../images/019.jpeg)\nOpen **Agent harnesses** in the left panel. You’ll see 11 built-in harnesses, including Codex, Claude Code, and Hermes. Select Hermes to create a task.\n![](../images/020.png)The supported harnesses also include Kimi Code.\nSelect a model, create a task, and follow the run in the Console.\nFiles created by the harness remain attached to that session:\n#### Configuring the paper workflow\nCreate two custom harnesses in the Console.\n\n```\nPaper Explainer with DeepSeek Harness\nPaper Explainer with Claude Code\n```\n\nThe first configuration uses DeepSeek Harness as its base harness. The second uses Codex. Both receive the same instructions and the same `paper-explainer` skill.\nThe skill defines the output expected by the paper application.\n\n```\nRead the uploaded research paper and identify its main mechanism.\nBuild a self-contained interactive explainer in index.html.\nInclude one controllable simulation with a short explanation beside it.\nUse Three.js only when 3D interaction improves the explanation.\nCreate README.md with the source, assumptions, and run instructions.\nVerify both files before completing the task.\n```\n\nThe following video depicts this setup:\nUpload the same paper to two new sessions. Run the same prompt through both configurations.\n\n```\nTurn the uploaded paper into an interactive visual explainer.\nRecreate its main mechanism as a controllable simulation.\nReturn index.html and README.md.\n```\n\nThe prompt, skill, and required files stay the same. Codex and DeepSeek Harness can still choose different plans, tools, and implementations.\n  * The first part of the video above shows the HarnessRouter dashboard and how the application selected and ran the harness.\n  * The final part of the video above shows what the agent produced.\n\n\n#### Calling a harness from the application\nAfter the task works in the Console, open `http://localhost:3000/keys`. Create a HarnessRouter API key and store it in backend code.\n![](../images/021.png)\nSet the local API address and the API key\n\n```\nexport HARNESSROUTER_BASE_URL=http://localhost:3000/api/harness\nexport HARNESSROUTER_API_KEY=sk-hr-...\n```\n\nSend a task through the Responses-compatible endpoint.\n\n```\ncurl --fail-with-body -sS \"$HARNESSROUTER_BASE_URL/v1/responses\" \\\n  -H \"Authorization: Bearer ${HARNESSROUTER_API_KEY:?}\" \\\n  -H \"content-type: application/json\" \\\n  -d '{\n    \"input\": \"Reply with exactly: it works.\",\n    \"metadata\": {\"harness_id\": \"codex\"},\n    \"model\": \"gpt-5.4-mini\",\n    \"stream\": false\n  }'\n```\n\nHere’s that request running against the local endpoint, with the response printed in the terminal:\nThis invocation uses the built-in `codex` identifier from the repository quickstart. A custom configuration uses the Harness ID shown in the Console.\nFor another new task, changing `metadata.harness_id` selects another configured harness.\nHere’s the demonstration with Hermes:\n\n```\ncurl --fail-with-body -sS \"$HARNESSROUTER_BASE_URL/v1/responses\" \\\n  -H \"Authorization: Bearer ${HARNESSROUTER_API_KEY:?}\" \\\n  -H \"content-type: application/json\" \\\n  -d '{\n    \"input\": \"Reply with exactly: it works.\",\n    \"metadata\": {\"harness_id\": \"hermes\"},\n    \"model\": \"gpt-5.4-mini\",\n    \"stream\": false\n  }'\n```\n\nAs depicted above, the application keeps the same endpoint and event format. The same client can also continue sessions, retrieve files, and cancel work.\n![](../images/022.jpeg)\n#### Session and security rules\nThe Unified Harness Protocol (UHP) standardizes the task lifecycle, but it does not make the harnesses behave the same. Different runtimes can choose different plans, tools, files, and models. The protocol gives the product one way to submit the work and inspect the result.\nThe local deployment also has a clear isolation limit. Sessions use separate operating-system users and workspaces. They do not run in separate containers. The Runner keeps the permissions needed to create those users, while each harness process runs as its assigned session user.\n![](../images/023.jpeg)\nProvider credentials should stay outside environments that agent tools can read. Application API keys should never reach browser code. A deployment outside loopback also needs TLS and the controls described in the UHP security specification.\n![](../images/024.jpeg)\n* * *\nThe two API calls above show why this matters when an agent becomes part of a product. Users may want to run a task with Codex, Claude Code, or Hermes.\nWithout a shared task interface, supporting each harness means writing another integration for progress, sessions, files, and cancellation.\nHarnessRouter lets the product offer that choice in its own UI.\nIt sends the task through UHP, selects the harness, and receives the result through the same API.\nThe team can test those workflows locally before putting them in front of users. As harnesses change, the product has a way to support more of them without rebuilding its task flow each time.\nHarnessRouter is Apache 2.0 licensed. The repository contains the self-hosted implementation, UHP schemas, and conformance tests.\nGitHub Repo: [**github.com/HarnessRouter/harnessrouter**](https://github.com/HarnessRouter/harnessrouter?ref=dailydoseofds.com).\n(don’t forget to star it ⭐️)\nGood day!\nPublished on Sep 23, 2026 \nComments \nShare \nCopy link [ Share to X ](https://x.com/intent/tweet?url=https%3A%2F%2Fwww.dailydoseofds.com%2Fp%2Frun-any-agent-harness-under-one-interface%2F&text=Run%20any%20agent%20harness%20under%20one%20interface) [ Share to Facebook ](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fwww.dailydoseofds.com%2Fp%2Frun-any-agent-harness-under-one-interface%2F) [ Share to Linkedin ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fwww.dailydoseofds.com%2Fp%2Frun-any-agent-harness-under-one-interface%2F)\nCopied \n[ Previous  Jev, Clearly Explained  ](https://www.dailydoseofds.com/p/jev-clearly-explained/) [ Next  Agent Harness with LangChain Middleware and Jev  ](https://www.dailydoseofds.com/ai-agents-with-langgraph-course-part-3-with-implementation/)\n[ ![Daily Dose of Data Science](https://storage.ghost.io/c/3f/df/3fdf6ed2-17ac-4b12-a693-8078bd13e748/content/images/2025/12/dailyds-logo-transparent-1.png) ](https://www.dailydoseofds.com)\nA daily column with insights, observations, tutorials and best practices on python and data science. Read by industry professionals at big tech, startups, and engineering students. \n  * Menu \n  * [ Contact ](https://www.dailydoseofds.com/contact/)\n  * [ FAQ ](https://www.dailydoseofds.com/faq/)\n\n\n[Daily Dose of Data Science](https://www.dailydoseofds.com) © 2026 \n[ ](https://x.com/_avichawla \"X \\(Formerly Twitter\\)\")\n",
  "metadata": {
    "title": "Run any agent harness under one interface",
    "description": "How UHP and HarnessRouter standardize agent execution across Codex, Claude Code, Hermes, and other runtimes.",
    "keywords": null,
    "author": null,
    "og:site_name": "Daily Dose of Data Science",
    "og:type": "article",
    "og:title": "Run any agent harness under one interface",
    "og:description": "How UHP and HarnessRouter standardize agent execution across Codex, Claude Code, Hermes, and other runtimes.",
    "og:url": "https://www.dailydoseofds.com/p/run-any-agent-harness-under-one-interface/",
    "og:image": "https://storage.ghost.io/c/3f/df/3fdf6ed2-17ac-4b12-a693-8078bd13e748/content/images/2026/09/48225cdb-89dd-4864-bf9c-c1f0438904a2_1136x991.png",
    "og:image:width": "1136",
    "og:image:height": "991",
    "twitter:card": "summary_large_image",
    "twitter:title": "Run any agent harness under one interface",
    "twitter:description": "How UHP and HarnessRouter standardize agent execution across Codex, Claude Code, Hermes, and other runtimes.",
    "twitter:url": "https://www.dailydoseofds.com/p/run-any-agent-harness-under-one-interface/",
    "twitter:image": "https://storage.ghost.io/c/3f/df/3fdf6ed2-17ac-4b12-a693-8078bd13e748/content/images/2026/09/48225cdb-89dd-4864-bf9c-c1f0438904a2_1136x991.png",
    "twitter:label1": "Written by",
    "twitter:data1": "Avi Chawla",
    "twitter:label2": "Filed under",
    "twitter:data2": "Agent Harness",
    "twitter:site": "@_avichawla",
    "article:published_time": "2026-09-23T17:50:00.000Z",
    "article:modified_time": "2026-09-28T17:51:20.000Z",
    "article:tag": "Agent Harness"
  },
  "paywall": {
    "listed_paid": false,
    "detected": false,
    "marker": "",
    "public_only": false,
    "policy": "付费/会员内容只保留页面公开可见部分，不绕过付费墙"
  },
  "crawl": {
    "success": true,
    "status_code": 200,
    "error": ""
  },
  "code_blocks": [
    {
      "language": "txt",
      "file": "attachments/c067df749b61/code/block_000.txt",
      "chars": 121
    },
    {
      "language": "txt",
      "file": "attachments/c067df749b61/code/block_001.txt",
      "chars": 29
    },
    {
      "language": "txt",
      "file": "attachments/c067df749b61/code/block_002.txt",
      "chars": 31
    },
    {
      "language": "txt",
      "file": "attachments/c067df749b61/code/block_003.txt",
      "chars": 71
    },
    {
      "language": "txt",
      "file": "attachments/c067df749b61/code/block_004.txt",
      "chars": 377
    },
    {
      "language": "txt",
      "file": "attachments/c067df749b61/code/block_005.txt",
      "chars": 153
    },
    {
      "language": "txt",
      "file": "attachments/c067df749b61/code/block_006.txt",
      "chars": 103
    },
    {
      "language": "txt",
      "file": "attachments/c067df749b61/code/block_007.txt",
      "chars": 314
    },
    {
      "language": "txt",
      "file": "attachments/c067df749b61/code/block_008.txt",
      "chars": 315
    }
  ],
  "images": [
    {
      "src": "https://storage.ghost.io/c/3f/df/3fdf6ed2-17ac-4b12-a693-8078bd13e748/content/images/size/w400/2026/03/avi-google.jpg",
      "alt": "Avi Chawla",
      "local_path": "attachments/c067df749b61/images/000.jpg",
      "bytes": 11344,
      "downloaded": true,
      "status": "ok",
      "url": "https://storage.ghost.io/c/3f/df/3fdf6ed2-17ac-4b12-a693-8078bd13e748/content/images/size/w400/2026/03/avi-google.jpg",
      "reused": true,
      "retried_at": "2026-10-18T17:06:46Z"
    },
    {
      "src": "https://substackcdn.com/image/fetch/$s_!Nyz2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feab76627-2fd7-45c5-a097-5e9a65aa3f04_2752x1536.jpeg",
      "alt": "",
      "local_path": "attachments/c067df749b61/images/001.jpeg",
      "bytes": 266184,
      "downloaded": true,
      "status": "ok",
      "url": "https://substackcdn.com/image/fetch/$s_!Nyz2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feab76627-2fd7-45c5-a097-5e9a65aa3f04_2752x1536.jpeg",
      "reused": true,
      "retried_at": "2026-10-18T17:06:46Z"
    },
    {
      "src": "https://substackcdn.com/image/fetch/$s_!2FRE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8cc2009-7ea7-46ba-9595-9ac5378d16fc_2752x1536.jpeg",
      "alt": "",
      "local_path": "attachments/c067df749b61/images/002.jpeg",
      "bytes": 100132,
      "downloaded": true,
      "status": "ok",
      "url": "https://substackcdn.com/image/fetch/$s_!2FRE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8cc2009-7ea7-46ba-9595-9ac5378d16fc_2752x1536.jpeg",
      "reused": true,
      "retried_at": "2026-10-18T17:06:46Z"
    },
    {
      "src": "https://substackcdn.com/image/fetch/$s_!517v!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F48225cdb-89dd-4864-bf9c-c1f0438904a2_1136x991.png",
      "alt": "",
      "local_path": "attachments/c067df749b61/images/003.png",
      "bytes": 80691,
      "downloaded": true,
      "status": "ok",
      "url": "https://substackcdn.com/image/fetch/$s_!517v!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F48225cdb-89dd-4864-bf9c-c1f0438904a2_1136x991.png",
      "reused": true,
      "retried_at": "2026-10-18T17:07:23Z"
    },
    {
      "src": "https://substackcdn.com/image/fetch/$s_!NI3V!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3df893e6-25a2-43bc-ab58-d679a2b63f31_2752x1536.jpeg",
      "alt": "",
      "local_path": "attachments/c067df749b61/images/004.jpeg",
      "bytes": 256769,
      "downloaded": true,
      "status": "ok",
      "url": "https://substackcdn.com/image/fetch/$s_!NI3V!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3df893e6-25a2-43bc-ab58-d679a2b63f31_2752x1536.jpeg",
      "reused": true,
      "retried_at": "2026-10-18T17:07:23Z"
    },
    {
      "src": "https://substackcdn.com/image/fetch/$s_!4-cm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24bcef30-5d93-4451-a32d-f85d4de9ae98_2752x1536.jpeg",
      "alt": "",
      "local_path": "attachments/c067df749b61/images/005.jpeg",
      "bytes": 242466,
      "downloaded": true,
      "status": "ok",
      "url": "https://substackcdn.com/image/fetch/$s_!4-cm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24bcef30-5d93-4451-a32d-f85d4de9ae98_2752x1536.jpeg",
      "reused": true,
      "retried_at": "2026-10-18T17:07:23Z"
    },
    {
      "src": "https://substackcdn.com/image/fetch/$s_!urs4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe7e984a-1a35-4f0f-8e22-78e544a68b72_2752x1536.jpeg",
      "alt": "",
      "local_path": "attachments/c067df749b61/images/006.jpeg",
      "bytes": 207475,
      "downloaded": true,
      "status": "ok",
      "url": "https://substackcdn.com/image/fetch/$s_!urs4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe7e984a-1a35-4f0f-8e22-78e544a68b72_2752x1536.jpeg",
      "reused": true,
      "retried_at": "2026-10-18T17:07:23Z"
    },
    {
      "src": "https://substackcdn.com/image/fetch/$s_!lz7Z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F861d375e-6d4a-4c8c-8e5d-5f80394f6cd1_2752x1536.jpeg",
      "alt": "",
      "local_path": "attachments/c067df749b61/images/007.jpeg",
      "bytes": 284724,
      "downloaded": true,
      "status": "ok",
      "url": "https://substackcdn.com/image/fetch/$s_!lz7Z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F861d375e-6d4a-4c8c-8e5d-5f80394f6cd1_2752x1536.jpeg",
      "reused": true,
      "retried_at": "2026-10-18T17:07:23Z"
    },
    {
      "src": "https://substackcdn.com/image/fetch/$s_!VJpK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67e80613-3423-4fc9-a702-f7f451cedb02_2639x1262.jpeg",
      "alt": "",
      "local_path": "attachments/c067df749b61/images/008.jpeg",
      "bytes": 264888,
      "downloaded": true,
      "status": "ok",
      "url": "https://substackcdn.com/image/fetch/$s_!VJpK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67e80613-3423-4fc9-a702-f7f451cedb02_2639x1262.jpeg",
      "reused": true,
      "retried_at": "2026-10-18T17:07:23Z"
    },
    {
      "src": "https://substackcdn.com/image/fetch/$s_!QQOh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9af5cd27-1cc8-40ae-9ed2-0f941cabf781_2752x1536.jpeg",
      "alt": "",
      "local_path": "attachments/c067df749b61/images/009.jpeg",
      "bytes": 265963,
      "downloaded": true,
      "status": "ok",
      "url": "https://substackcdn.com/image/fetch/$s_!QQOh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9af5cd27-1cc8-40ae-9ed2-0f941cabf781_2752x1536.jpeg",
      "reused": true,
      "retried_at": "2026-10-18T17:07:23Z"
    },
    {
      "src": "https://substackcdn.com/image/fetch/$s_!6Lfb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38e43003-695a-473d-a99b-7cbe0d70a5da_2752x1536.jpeg",
      "alt": "",
      "local_path": "attachments/c067df749b61/images/010.jpeg",
      "bytes": 226844,
      "downloaded": true,
      "status": "ok",
      "url": "https://substackcdn.com/image/fetch/$s_!6Lfb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38e43003-695a-473d-a99b-7cbe0d70a5da_2752x1536.jpeg",
      "reused": true,
      "retried_at": "2026-10-18T17:07:23Z"
    },
    {
      "src": "https://substackcdn.com/image/fetch/$s_!JDaJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdfd7c4c-4a8e-4ac1-ad50-6e169c8dfa34_2752x1536.jpeg",
      "alt": "",
      "local_path": "attachments/c067df749b61/images/011.jpeg",
      "bytes": 264102,
      "downloaded": true,
      "status": "ok",
      "url": "https://substackcdn.com/image/fetch/$s_!JDaJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdfd7c4c-4a8e-4ac1-ad50-6e169c8dfa34_2752x1536.jpeg",
      "reused": true,
      "retried_at": "2026-10-18T17:07:23Z"
    },
    {
      "src": "https://substackcdn.com/image/fetch/$s_!3SuG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc241b978-80d7-4a39-b41a-8707efdc8a1a_2752x1536.jpeg",
      "alt": "",
      "local_path": "attachments/c067df749b61/images/012.jpeg",
      "bytes": 245372,
      "downloaded": true,
      "status": "ok",
      "url": "https://substackcdn.com/image/fetch/$s_!3SuG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc241b978-80d7-4a39-b41a-8707efdc8a1a_2752x1536.jpeg",
      "reused": true,
      "retried_at": "2026-10-18T17:07:23Z"
    },
    {
      "src": "https://substackcdn.com/image/fetch/$s_!xM6Y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42321125-6a76-461f-a1fe-b92f90037da7_2752x1536.jpeg",
      "alt": "",
      "local_path": "attachments/c067df749b61/images/013.jpeg",
      "bytes": 275461,
      "downloaded": true,
      "status": "ok",
      "url": "https://substackcdn.com/image/fetch/$s_!xM6Y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42321125-6a76-461f-a1fe-b92f90037da7_2752x1536.jpeg",
      "reused": true,
      "retried_at": "2026-10-18T17:07:23Z"
    },
    {
      "src": "https://substackcdn.com/image/fetch/$s_!ka21!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa48c7799-77b7-4ba7-b9c1-f09d01dce79c_2752x1536.jpeg",
      "alt": "",
      "local_path": "attachments/c067df749b61/images/014.jpeg",
      "bytes": 223045,
      "downloaded": true,
      "status": "ok",
      "url": "https://substackcdn.com/image/fetch/$s_!ka21!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa48c7799-77b7-4ba7-b9c1-f09d01dce79c_2752x1536.jpeg",
      "reused": true,
      "retried_at": "2026-10-18T17:07:23Z"
    },
    {
      "src": "https://substackcdn.com/image/fetch/$s_!2mJO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b035c36-77c1-4231-ae17-0176db6bd85e_1320x430.png",
      "alt": "",
      "local_path": "attachments/c067df749b61/images/015.png",
      "bytes": 61056,
      "downloaded": true,
      "status": "ok",
      "url": "https://substackcdn.com/image/fetch/$s_!2mJO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b035c36-77c1-4231-ae17-0176db6bd85e_1320x430.png",
      "reused": true,
      "retried_at": "2026-10-18T17:07:23Z"
    },
    {
      "src": "https://substackcdn.com/image/fetch/$s_!fJO2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcae33448-5d14-4a1b-852a-59841d8b84d5_1300x714.png",
      "alt": "",
      "local_path": "attachments/c067df749b61/images/016.png",
      "bytes": 88172,
      "downloaded": true,
      "status": "ok",
      "url": "https://substackcdn.com/image/fetch/$s_!fJO2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcae33448-5d14-4a1b-852a-59841d8b84d5_1300x714.png",
      "reused": true,
      "retried_at": "2026-10-18T17:07:23Z"
    },
    {
      "src": "https://substackcdn.com/image/fetch/$s_!f5ic!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73135d06-2589-4fb6-8c1e-245277d089bd_1339x857.png",
      "alt": "",
      "local_path": "attachments/c067df749b61/images/017.png",
      "bytes": 80876,
      "downloaded": true,
      "status": "ok",
      "url": "https://substackcdn.com/image/fetch/$s_!f5ic!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73135d06-2589-4fb6-8c1e-245277d089bd_1339x857.png",
      "reused": true,
      "retried_at": "2026-10-18T17:07:23Z"
    },
    {
      "src": "https://substackcdn.com/image/fetch/$s_!wj8k!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3966d377-3508-4a4a-af93-002eca5f8f03_1734x1183.png",
      "alt": "",
      "local_path": "attachments/c067df749b61/images/018.png",
      "bytes": 192005,
      "downloaded": true,
      "status": "ok",
      "url": "https://substackcdn.com/image/fetch/$s_!wj8k!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3966d377-3508-4a4a-af93-002eca5f8f03_1734x1183.png",
      "reused": true,
      "retried_at": "2026-10-18T17:07:23Z"
    },
    {
      "src": "https://substackcdn.com/image/fetch/$s_!Eju0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff709fb0d-7788-4b37-8b18-849b263da4fd_2752x1536.jpeg",
      "alt": "",
      "local_path": "attachments/c067df749b61/images/019.jpeg",
      "bytes": 98397,
      "downloaded": true,
      "status": "ok",
      "url": "https://substackcdn.com/image/fetch/$s_!Eju0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff709fb0d-7788-4b37-8b18-849b263da4fd_2752x1536.jpeg",
      "reused": true,
      "retried_at": "2026-10-18T17:07:23Z"
    },
    {
      "src": "https://substackcdn.com/image/fetch/$s_!mTwx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F059a841b-a4d1-4ca7-ac34-36ccd20b7d5a_1834x1140.png",
      "alt": "",
      "local_path": "attachments/c067df749b61/images/020.png",
      "bytes": 144413,
      "downloaded": true,
      "status": "ok",
      "url": "https://substackcdn.com/image/fetch/$s_!mTwx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F059a841b-a4d1-4ca7-ac34-36ccd20b7d5a_1834x1140.png",
      "reused": true,
      "retried_at": "2026-10-18T17:07:23Z"
    },
    {
      "src": "https://substackcdn.com/image/fetch/$s_!8uAz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07f8955f-7e80-455e-acc3-87bdc2aa1381_1497x967.png",
      "alt": "",
      "local_path": "attachments/c067df749b61/images/021.png",
      "bytes": 141992,
      "downloaded": true,
      "status": "ok",
      "url": "https://substackcdn.com/image/fetch/$s_!8uAz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07f8955f-7e80-455e-acc3-87bdc2aa1381_1497x967.png",
      "reused": true,
      "retried_at": "2026-10-18T17:07:23Z"
    },
    {
      "src": "https://substackcdn.com/image/fetch/$s_!npZV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c41213-9ed0-4ecb-8965-a4b5c4415816_2752x1536.jpeg",
      "alt": "",
      "local_path": "attachments/c067df749b61/images/022.jpeg",
      "bytes": 253185,
      "downloaded": true,
      "status": "ok",
      "url": "https://substackcdn.com/image/fetch/$s_!npZV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c41213-9ed0-4ecb-8965-a4b5c4415816_2752x1536.jpeg",
      "reused": true,
      "retried_at": "2026-10-18T17:07:23Z"
    },
    {
      "src": "https://substackcdn.com/image/fetch/$s_!lEY_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7aa0e8e5-8ebb-4ad7-8e15-2e4a4f3ad0e7_2752x1536.jpeg",
      "alt": "",
      "local_path": "attachments/c067df749b61/images/023.jpeg",
      "bytes": 271553,
      "downloaded": true,
      "status": "ok",
      "url": "https://substackcdn.com/image/fetch/$s_!lEY_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7aa0e8e5-8ebb-4ad7-8e15-2e4a4f3ad0e7_2752x1536.jpeg",
      "reused": true,
      "retried_at": "2026-10-18T17:07:23Z"
    },
    {
      "src": "https://substackcdn.com/image/fetch/$s_!UmZK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c844f2d-58a7-4eab-9a09-d59ed2ea144b_2604x1108.jpeg",
      "alt": "",
      "local_path": "attachments/c067df749b61/images/024.jpeg",
      "bytes": 191992,
      "downloaded": true,
      "status": "ok",
      "url": "https://substackcdn.com/image/fetch/$s_!UmZK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c844f2d-58a7-4eab-9a09-d59ed2ea144b_2604x1108.jpeg",
      "reused": true,
      "retried_at": "2026-10-18T17:07:23Z"
    }
  ],
  "audio": [],
  "videos": [
    {
      "src": "https://storage.ghost.io/c/3f/df/3fdf6ed2-17ac-4b12-a693-8078bd13e748/content/media/2026/09/1-harnessrouter-invoke-harness.mp4",
      "quality": "unavailable",
      "local_path": "attachments/c067df749b61/videos/repair-2c1fdca9c93ffb5d0abb.mp4",
      "note": "无1080p且无720p，未交付更低清晰度",
      "url": "https://storage.ghost.io/c/3f/df/3fdf6ed2-17ac-4b12-a693-8078bd13e748/content/media/2026/09/1-harnessrouter-invoke-harness.mp4",
      "title": "",
      "status": "ok",
      "bytes": 37641472,
      "reused": false,
      "content_type": "video/mp4",
      "valid": true,
      "height": 1080,
      "width": 1700,
      "duration": "25.916667",
      "retried_at": "2026-10-18T17:07:30Z"
    },
    {
      "src": "https://storage.ghost.io/c/3f/df/3fdf6ed2-17ac-4b12-a693-8078bd13e748/content/media/2026/09/2-harnessrouter-build-custom-mp4.mp4",
      "quality": "unavailable",
      "local_path": "attachments/c067df749b61/videos/repair-6aec0b102cfe76d4f49c.mp4",
      "note": "无1080p且无720p，未交付更低清晰度",
      "url": "https://storage.ghost.io/c/3f/df/3fdf6ed2-17ac-4b12-a693-8078bd13e748/content/media/2026/09/2-harnessrouter-build-custom-mp4.mp4",
      "title": "",
      "status": "ok",
      "bytes": 47937373,
      "reused": false,
      "content_type": "video/mp4",
      "valid": true,
      "height": 1080,
      "width": 1700,
      "duration": "28.783333",
      "retried_at": "2026-10-18T17:07:32Z"
    }
  ],
  "links": [
    {
      "type": "internal",
      "href": "https://www.dailydoseofds.com/p/run-any-agent-harness-under-one-interface/"
    },
    {
      "type": "internal",
      "href": "https://www.dailydoseofds.com"
    },
    {
      "type": "internal",
      "href": "https://www.dailydoseofds.com/archive/"
    },
    {
      "type": "internal",
      "href": "https://www.dailydoseofds.com/what-is-mcp/"
    },
    {
      "type": "internal",
      "href": "https://www.dailydoseofds.com/"
    },
    {
      "type": "internal",
      "href": "https://www.dailydoseofds.com/mlops-crash-course-part-1/"
    },
    {
      "type": "internal",
      "href": "https://www.dailydoseofds.com/rl-course-part-1/"
    },
    {
      "type": "internal",
      "href": "https://www.dailydoseofds.com/ai-agents-crash-course-part-1-with-implementation/"
    },
    {
      "type": "internal",
      "href": "https://www.dailydoseofds.com/model-context-protocol-crash-course-part-1/"
    },
    {
      "type": "internal",
      "href": "https://www.dailydoseofds.com/a-crash-course-on-building-rag-systems-part-1-with-implementations/"
    },
    {
      "type": "internal",
      "href": "https://www.dailydoseofds.com/bi-encoders-and-cross-encoders-for-sentence-pair-similarity-scoring-part-1/"
    },
    {
      "type": "internal",
      "href": "https://www.dailydoseofds.com/where-did-the-assumptions-of-linear-regression-originate-from/"
    },
    {
      "type": "internal",
      "href": "https://www.dailydoseofds.com/8-fatal-yet-non-obvious-pitfalls-and-cautionary-measures-in-data-science/"
    },
    {
      "type": "internal",
      "href": "https://www.dailydoseofds.com/membership"
    },
    {
      "type": "internal",
      "href": "https://www.dailydoseofds.com/p/jev-clearly-explained/"
    },
    {
      "type": "internal",
      "href": "https://www.dailydoseofds.com/ai-agents-with-langgraph-course-part-3-with-implementation/"
    },
    {
      "type": "internal",
      "href": "https://www.dailydoseofds.com/contact/"
    },
    {
      "type": "internal",
      "href": "https://www.dailydoseofds.com/faq/"
    },
    {
      "type": "external",
      "href": "https://dailydoseofds.github.io/ai-engg-book/"
    },
    {
      "type": "external",
      "href": "https://drive.google.com/file/d/1Th8mN_IF7Ttc8bI_OLtUuQ7Mjx3aJ6Hi/view"
    },
    {
      "type": "external",
      "href": "https://drive.google.com/file/d/1_s2UaD7tEPECjgC5YMOa1LIOB9HUWFO-/view"
    },
    {
      "type": "external",
      "href": "https://drive.google.com/file/d/1ZunUHwkD2Ut0_LrgDTDmlQRQkfT2lkVf/view"
    },
    {
      "type": "external",
      "href": "https://github.com/HarnessRouter/harnessrouter"
    },
    {
      "type": "external",
      "href": "https://x.com/intent/tweet?text=Run+any+agent+harness+under+one+interface&url=https%3A%2F%2Fwww.dailydoseofds.com%2Fp%2Frun-any-agent-harness-under-one-interface%2F"
    },
    {
      "type": "external",
      "href": "https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fwww.dailydoseofds.com%2Fp%2Frun-any-agent-harness-under-one-interface%2F"
    },
    {
      "type": "external",
      "href": "https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fwww.dailydoseofds.com%2Fp%2Frun-any-agent-harness-under-one-interface%2F"
    },
    {
      "type": "external",
      "href": "https://x.com/_avichawla"
    }
  ],
  "repair_version": 2,
  "repaired_at": "2026-10-20T17:24:03Z",
  "source_url": "https://www.dailydoseofds.com/p/run-any-agent-harness-under-one-interface/",
  "delivery_status": "unverified",
  "discovery_status": "short_or_dynamic",
  "missing_reason": "正文过短或动态页面，未确认完整",
  "source_body_markdown": "[ Skip to main content  ](https://www.dailydoseofds.com/p/run-any-agent-harness-under-one-interface/#sx-main)\n[ ![Daily Dose of Data Science](https://storage.ghost.io/c/3f/df/3fdf6ed2-17ac-4b12-a693-8078bd13e748/content/images/2025/12/dailyds-logo-transparent-1.png) ](https://www.dailydoseofds.com)\n  * [ Newsletter ](https://dailydoseofds.github.io/ai-engg-book/)\n  * [ Archive ](https://www.dailydoseofds.com/archive/)\n  * Guidebooks \n    * [ MCP Guidebook ](https://www.dailydoseofds.com/what-is-mcp/)\n[ Agents Guidebook ](https://drive.google.com/file/d/1Th8mN_IF7Ttc8bI_OLtUuQ7Mjx3aJ6Hi/view)\n[ AI Engineering Guidebook ](https://drive.google.com/file/d/1_s2UaD7tEPECjgC5YMOa1LIOB9HUWFO-/view)\n[ DS Guidebook ](https://drive.google.com/file/d/1ZunUHwkD2Ut0_LrgDTDmlQRQkfT2lkVf/view)\n[ Courses ](https://www.dailydoseofds.com/)\n[ MLOps/LLMOps Course ](https://www.dailydoseofds.com/mlops-crash-course-part-1/)\n[ Reinforcement Learning Course ](https://www.dailydoseofds.com/rl-course-part-1/)\n[ AI Agents Course ](https://www.dailydoseofds.com/ai-agents-crash-course-part-1-with-implementation/)\n[ MCP Course ](https://www.dailydoseofds.com/model-context-protocol-crash-course-part-1/)\n[ RAG Systems Course ](https://www.dailydoseofds.com/a-crash-course-on-building-rag-systems-part-1-with-implementations/)\n  * Courses \n    * [ MLOps/LLMOps Course ](https://www.dailydoseofds.com/mlops-crash-course-part-1/)\n[ Reinforcement Learning Course ](https://www.dailydoseofds.com/rl-course-part-1/)\n[ AI Agents Course ](https://www.dailydoseofds.com/ai-agents-crash-course-part-1-with-implementation/)\n[ MCP Course ](https://www.dailydoseofds.com/model-context-protocol-crash-course-part-1/)\n[ RAG Systems Course ](https://www.dailydoseofds.com/a-crash-course-on-building-rag-systems-part-1-with-implementations/)\n[ LLM and Fine-tuning ](https://www.dailydoseofds.com/bi-encoders-and-cross-encoders-for-sentence-pair-similarity-scoring-part-1/)\n[ Classical ML and Deep Learning ](https://www.dailydoseofds.com/where-did-the-assumptions-of-linear-regression-originate-from/)\n[ Engineering Best Practices ](https://www.dailydoseofds.com/8-fatal-yet-non-obvious-pitfalls-and-cautionary-measures-in-data-science/)\n  *     * [ Newsletter ](https://dailydoseofds.github.io/ai-engg-book/)\n[ Archive ](https://www.dailydoseofds.com/archive/)\nGuidebooks \n      * [ MCP Guidebook ](https://www.dailydoseofds.com/what-is-mcp/)\n      * [ Agents Guidebook ](https://drive.google.com/file/d/1Th8mN_IF7Ttc8bI_OLtUuQ7Mjx3aJ6Hi/view)\n      * [ AI Engineering Guidebook ](https://drive.google.com/file/d/1_s2UaD7tEPECjgC5YMOa1LIOB9HUWFO-/view)\n      * [ DS Guidebook ](https://drive.google.com/file/d/1ZunUHwkD2Ut0_LrgDTDmlQRQkfT2lkVf/view)\n      * [ Courses ](https://www.dailydoseofds.com/)\n      * [ MLOps/LLMOps Course ](https://www.dailydoseofds.com/mlops-crash-course-part-1/)\n      * [ Reinforcement Learning Course ](https://www.dailydoseofds.com/rl-course-part-1/)\n      * [ AI Agents Course ](https://www.dailydoseofds.com/ai-agents-crash-course-part-1-with-implementation/)\n      * [ MCP Course ](https://www.dailydoseofds.com/model-context-protocol-crash-course-part-1/)\n      * [ RAG Systems Course ](https://www.dailydoseofds.com/a-crash-course-on-building-rag-systems-part-1-with-implementations/)\nCourses \n      * [ MLOps/LLMOps Course ](https://www.dailydoseofds.com/mlops-crash-course-part-1/)\n      * [ Reinforcement Learning Course ](https://www.dailydoseofds.com/rl-course-part-1/)\n      * [ AI Agents Course ](https://www.dailydoseofds.com/ai-agents-crash-course-part-1-with-implementation/)\n      * [ MCP Course ](https://www.dailydoseofds.com/model-context-protocol-crash-course-part-1/)\n      * [ RAG Systems Course ](https://www.dailydoseofds.com/a-crash-course-on-building-rag-systems-part-1-with-implementations/)\n      * [ LLM and Fine-tuning ](https://www.dailydoseofds.com/bi-encoders-and-cross-encoders-for-sentence-pair-similarity-scoring-part-1/)\n      * [ Classical ML and Deep Learning ](https://www.dailydoseofds.com/where-did-the-assumptions-of-linear-regression-originate-from/)\n      * [ Engineering Best Practices ](https://www.dailydoseofds.com/8-fatal-yet-non-obvious-pitfalls-and-cautionary-measures-in-data-science/)\n\n\nSign In  [ Get Started ](https://www.dailydoseofds.com/membership)\n/\n  * [ Newsletter ](https://dailydoseofds.github.io/ai-engg-book/)\n  * [ Archive ](https://www.dailydoseofds.com/archive/)\n  * Guidebooks \n    * [ MCP Guidebook ](https://www.dailydoseofds.com/what-is-mcp/)\n    * [ Agents Guidebook ](https://drive.google.com/file/d/1Th8mN_IF7Ttc8bI_OLtUuQ7Mjx3aJ6Hi/view)\n    * [ AI Engineering Guidebook ](https://drive.google.com/file/d/1_s2UaD7tEPECjgC5YMOa1LIOB9HUWFO-/view)\n    * [ DS Guidebook ](https://drive.google.com/file/d/1ZunUHwkD2Ut0_LrgDTDmlQRQkfT2lkVf/view)\n    * [ Courses ](https://www.dailydoseofds.com/)\n    * [ MLOps/LLMOps Course ](https://www.dailydoseofds.com/mlops-crash-course-part-1/)\n    * [ Reinforcement Learning Course ](https://www.dailydoseofds.com/rl-course-part-1/)\n    * [ AI Agents Course ](https://www.dailydoseofds.com/ai-agents-crash-course-part-1-with-implementation/)\n    * [ MCP Course ](https://www.dailydoseofds.com/model-context-protocol-crash-course-part-1/)\n    * [ RAG Systems Course ](https://www.dailydoseofds.com/a-crash-course-on-building-rag-systems-part-1-with-implementations/)\n  * Courses \n    * [ MLOps/LLMOps Course ](https://www.dailydoseofds.com/mlops-crash-course-part-1/)\n    * [ Reinforcement Learning Course ](https://www.dailydoseofds.com/rl-course-part-1/)\n    * [ AI Agents Course ](https://www.dailydoseofds.com/ai-agents-crash-course-part-1-with-implementation/)\n    * [ MCP Course ](https://www.dailydoseofds.com/model-context-protocol-crash-course-part-1/)\n    * [ RAG Systems Course ](https://www.dailydoseofds.com/a-crash-course-on-building-rag-systems-part-1-with-implementations/)\n    * [ LLM and Fine-tuning ](https://www.dailydoseofds.com/bi-encoders-and-cross-encoders-for-sentence-pair-similarity-scoring-part-1/)\n    * [ Classical ML and Deep Learning ](https://www.dailydoseofds.com/where-did-the-assumptions-of-linear-regression-originate-from/)\n    * [ Engineering Best Practices ](https://www.dailydoseofds.com/8-fatal-yet-non-obvious-pitfalls-and-cautionary-measures-in-data-science/)\n  * Sign In \n\n\nSep 23, 2026  Agent Harness \n#  Run any agent harness under one interface \nHow UHP and HarnessRouter standardize agent execution across Codex, Claude Code, Hermes, and other runtimes. \n![Avi Chawla](https://storage.ghost.io/c/3f/df/3fdf6ed2-17ac-4b12-a693-8078bd13e748/content/images/size/w400/2026/03/avi-google.jpg)\nAvi Chawla \n👉\n* * *\nWhen an agent product integrates one harness directly, its backend starts depending on that harness’s task format, event stream, session model, and filesystem behavior.\nUnlike model routing, adding another harness is not a config/parameter change because it adds another runtime that plans work, calls tools, manages files, and decides when a task is complete.\n![](https://substackcdn.com/image/fetch/$s_!Nyz2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feab76627-2fd7-45c5-a097-5e9a65aa3f04_2752x1536.jpeg)\nAnd supporting more than one runtime is critical since harnesses are built differently.\nThe right choice can depend on the task, required tools, provider access, available models, cost, latency, or usage limits. Like models, a product should be able to add or replace a harness without rebuilding the feature around it.\nModel routing does not solve that problem. It chooses which model handles an inference request, while the same agent loop remains in place. Harness routing chooses the agent runtime that owns the complete task.\n![](https://substackcdn.com/image/fetch/$s_!2FRE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8cc2009-7ea7-46ba-9595-9ac5378d16fc_2752x1536.jpeg)\nToday, let’s talk about the engineering behind that second form of routing. We will understand why products may need different harnesses, what must be standardized across them, and how the [**Unified Harness Protocol**](https://github.com/HarnessRouter/harnessrouter?ref=dailydoseofds.com) defines that contract.\nWe will then use [**HarnessRouter**](https://github.com/HarnessRouter/harnessrouter?ref=dailydoseofds.com), an open-source UHP implementation, to run the same workflow through Codex and Claude Code.\n![](https://substackcdn.com/image/fetch/$s_!517v!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F48225cdb-89dd-4864-bf9c-c1f0438904a2_1136x991.png)\n#### Why a product may need another harness\nHarnesses make different choices about tool execution, context management, permissions, skills, and supported models. The same harness may not provide the right tools or model support for every product feature.\n![](https://substackcdn.com/image/fetch/$s_!NI3V!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3df893e6-25a2-43bc-ab58-d679a2b63f31_2752x1536.jpeg)\nA product may also serve customers with different provider access. One customer may already use OpenAI models, while another is set up around Anthropic. A quota or provider outage can also make one backend unavailable.\n![](https://substackcdn.com/image/fetch/$s_!4-cm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24bcef30-5d93-4451-a32d-f85d4de9ae98_2752x1536.jpeg)\nEvaluation is another reason. Running the same task through two harnesses makes their cost, latency, tool use, and output easier to compare. The comparison is difficult when each backend requires different task and event code.\nThe goal is not to switch harnesses during every session but rather to keep the product from depending on one runtime.\n![](https://substackcdn.com/image/fetch/$s_!urs4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe7e984a-1a35-4f0f-8e22-78e544a68b72_2752x1536.jpeg)\nA team can select a harness per feature, offer a supported choice to customers, or replace a backend without changing the product workflow.\n#### A model call does not run the whole task\nA model API accepts input and returns generated output. The application still runs requested tools, starts follow-up model calls, and manages files, permissions, retries, and task state.\n![](https://substackcdn.com/image/fetch/$s_!lz7Z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F861d375e-6d4a-4c8c-8e5d-5f80394f6cd1_2752x1536.jpeg)\nAn agent harness includes this control loop. It can inspect files, call tools, edit a project, run commands, review the output, and decide when to stop.\nCodex and Claude Code can use similar models and still behave differently. Their instructions, tools, context handling, permissions, and completion rules affect the run.\n#### Model routing vs. harness routing\nModel routing happens inside the inference layer. It chooses an endpoint based on price, latency, context length, availability, or measured quality. The application or harness still owns the agent loop.\nHarness routing selects the runtime that owns the task. That choice can change the tools, skills, workspace, permissions, and event stream.\n![](https://substackcdn.com/image/fetch/$s_!VJpK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67e80613-3423-4fc9-a702-f7f451cedb02_2639x1262.jpeg)\nA product may use both routing layers. In UHP, `model` chooses the model, while `metadata.harness_id` chooses the configured harness.\n#### What the product must handle for each harness\nThe first integration often starts as a small adapter that launches a process and reads its output. A product UI also needs live progress, session continuity, file uploads, download links, and access rules.\n![](https://substackcdn.com/image/fetch/$s_!QQOh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9af5cd27-1cc8-40ae-9ed2-0f941cabf781_2752x1536.jpeg)\nCancellation needs a defined path because local processes, remote jobs, and sessions stop differently. Errors also need enough structure to separate provider failures, permission denials, time limits, missing files, and cancelled tasks.\nAdding Claude Code beside Codex means building and maintaining these mappings again. The product needs one task lifecycle that both integrations can follow.\n#### The task lifecycle defined by UHP\nThe Unified Harness Protocol defines the HTTP contract between an application and a harness server. It covers task creation, progress, sessions, files, cancellation, and errors without defining how the harness plans.\n![](https://substackcdn.com/image/fetch/$s_!6Lfb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38e43003-695a-473d-a99b-7cbe0d70a5da_2752x1536.jpeg)\nUHP uses an API shaped like the OpenAI Responses API. A client starts work through `POST /v1/responses`. The request includes the task input, model, configured Harness ID, and optional execution limits.\nA response records one task. A session groups related responses that share conversation state and a working directory. A configured harness combines a base harness with its model, instructions, skills, tools, MCP servers, and limits.\n![](https://substackcdn.com/image/fetch/$s_!JDaJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdfd7c4c-4a8e-4ac1-ad50-6e169c8dfa34_2752x1536.jpeg)\nLive tasks use Server-Sent Events, or SSE. Each event has a type and sequence number, so the client can process the stream in order.\nThe events report text output, tool activity, files, and task status. The application displays them without searching raw terminal lines for each event.\nUHP accepts small files in the request and larger files through uploads. Generated files become artifacts that the application can list and download. The files specification defines those operations.\nFollow-up tasks use `previous_response_id`. The server continues the same session with its conversation, working directory, files, and configured harness.\nYou can still hand off work to another harness. If Codex starts a task and you want Claude Code to take over, start a new session with Claude Code and pass it the relevant context, such as a summary of the work so far, the next instructions, and any files it needs. Think of it as handing a task to another developer: the work can continue, but Claude Code is not resuming Codex’s session.\n![](https://substackcdn.com/image/fetch/$s_!3SuG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc241b978-80d7-4a39-b41a-8707efdc8a1a_2752x1536.jpeg)\nFor comparison, the application starts two sessions and gives both the same PDF and prompt. Each harness receives clear input instead of hidden state created by another runtime. The session specification documents this rule.\nThe current UHP version is `2026-09-12`. The project publishes the written specification, OpenAPI 3.1 schema, JSON Schema definitions, and runnable conformance checks.\n#### How HarnessRouter runs a task\nHarnessRouter ([**GitHub Repo**](https://github.com/HarnessRouter/harnessrouter?ref=dailydoseofds.com)) is a self-hosted UHP server. It receives a UHP request, reads the Harness ID, and starts the selected runtime. As the harness works, HarnessRouter records its output as UHP events, responses, sessions, files, and errors.\nThe Docker image contains three services.\nThe Console provides the browser UI. The Gateway handles the UHP API and harness configuration. The Runner starts harness processes inside session workspaces.\nA named `/data` volume stores the database, installed harness CLIs, provider integrations, session files, and workspaces. Only the Console port is published. The Gateway and Runner listen on loopback inside the container.\n![](https://substackcdn.com/image/fetch/$s_!xM6Y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42321125-6a76-461f-a1fe-b92f90037da7_2752x1536.jpeg)\nThe self-hosting guide lists Codex, Claude Code, Hermes, DeepSeek Harness, Gemini CLI, OpenCode, Qwen Code, Cline, Goose, and other backends.\nA built-in harness can run without a custom configuration. A custom harness starts with one base harness and adds a default model, instructions, tools, skills, and optional MCP servers. HarnessRouter gives the saved configuration a Harness ID.\n![](https://substackcdn.com/image/fetch/$s_!ka21!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa48c7799-77b7-4ba7-b9c1-f09d01dce79c_2752x1536.jpeg)\nThe product sends this ID with each new task. It does not need to launch the harness CLI or parse the harness output itself.\n#### Running HarnessRouter locally\nCommunity Edition requires Docker, about 4 GB of disk, and an API key for a supported model provider.\nStart the container.\n\n```\ndocker run -d --name harnessrouter \\\n  -p 127.0.0.1:3000:3000 \\\n  -v harnessrouter:/data \\\n  harnessrouter/harnessrouter\n```\n\nThe `127.0.0.1` binding keeps the Console on the local machine. The named volume preserves its data across container restarts.\nFollow the startup logs.\n\n```\ndocker logs -f harnessrouter\n```\n\nThe first run installs the enabled harness CLIs:\n![](https://substackcdn.com/image/fetch/$s_!2mJO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b035c36-77c1-4231-ae17-0176db6bd85e_1320x430.png)\nWait for this message:\n![](https://substackcdn.com/image/fetch/$s_!fJO2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcae33448-5d14-4a1b-852a-59841d8b84d5_1300x714.png)\n```\n[harnessrouter] ready on :3000\n```\n\nOpen `http://localhost:3000`.\n![](https://substackcdn.com/image/fetch/$s_!f5ic!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73135d06-2589-4fb6-8c1e-245277d089bd_1339x857.png)The default username and password are both `harnessrouter`.\nNext, open **Integrations** in the left panel and select **Add Integration**. Choose a model provider and enter its API key:\n![](https://substackcdn.com/image/fetch/$s_!wj8k!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3966d377-3508-4a4a-af93-002eca5f8f03_1734x1183.png)\nThis key authorizes model requests. It is separate from the Console password and the API key later used by the application.\n![](https://substackcdn.com/image/fetch/$s_!Eju0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff709fb0d-7788-4b37-8b18-849b263da4fd_2752x1536.jpeg)\nOpen **Agent harnesses** in the left panel. You’ll see 11 built-in harnesses, including Codex, Claude Code, and Hermes. Select Hermes to create a task.\n![](https://substackcdn.com/image/fetch/$s_!mTwx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F059a841b-a4d1-4ca7-ac34-36ccd20b7d5a_1834x1140.png)The supported harnesses also include Kimi Code.\nSelect a model, create a task, and follow the run in the Console.\nFiles created by the harness remain attached to that session:\n#### Configuring the paper workflow\nCreate two custom harnesses in the Console.\n\n```\nPaper Explainer with DeepSeek Harness\nPaper Explainer with Claude Code\n```\n\nThe first configuration uses DeepSeek Harness as its base harness. The second uses Codex. Both receive the same instructions and the same `paper-explainer` skill.\nThe skill defines the output expected by the paper application.\n\n```\nRead the uploaded research paper and identify its main mechanism.\nBuild a self-contained interactive explainer in index.html.\nInclude one controllable simulation with a short explanation beside it.\nUse Three.js only when 3D interaction improves the explanation.\nCreate README.md with the source, assumptions, and run instructions.\nVerify both files before completing the task.\n```\n\nThe following video depicts this setup:\nUpload the same paper to two new sessions. Run the same prompt through both configurations.\n\n```\nTurn the uploaded paper into an interactive visual explainer.\nRecreate its main mechanism as a controllable simulation.\nReturn index.html and README.md.\n```\n\nThe prompt, skill, and required files stay the same. Codex and DeepSeek Harness can still choose different plans, tools, and implementations.\n  * The first part of the video above shows the HarnessRouter dashboard and how the application selected and ran the harness.\n  * The final part of the video above shows what the agent produced.\n\n\n#### Calling a harness from the application\nAfter the task works in the Console, open `http://localhost:3000/keys`. Create a HarnessRouter API key and store it in backend code.\n![](https://substackcdn.com/image/fetch/$s_!8uAz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07f8955f-7e80-455e-acc3-87bdc2aa1381_1497x967.png)\nSet the local API address and the API key\n\n```\nexport HARNESSROUTER_BASE_URL=http://localhost:3000/api/harness\nexport HARNESSROUTER_API_KEY=sk-hr-...\n```\n\nSend a task through the Responses-compatible endpoint.\n\n```\ncurl --fail-with-body -sS \"$HARNESSROUTER_BASE_URL/v1/responses\" \\\n  -H \"Authorization: Bearer ${HARNESSROUTER_API_KEY:?}\" \\\n  -H \"content-type: application/json\" \\\n  -d '{\n    \"input\": \"Reply with exactly: it works.\",\n    \"metadata\": {\"harness_id\": \"codex\"},\n    \"model\": \"gpt-5.4-mini\",\n    \"stream\": false\n  }'\n```\n\nHere’s that request running against the local endpoint, with the response printed in the terminal:\nThis invocation uses the built-in `codex` identifier from the repository quickstart. A custom configuration uses the Harness ID shown in the Console.\nFor another new task, changing `metadata.harness_id` selects another configured harness.\nHere’s the demonstration with Hermes:\n\n```\ncurl --fail-with-body -sS \"$HARNESSROUTER_BASE_URL/v1/responses\" \\\n  -H \"Authorization: Bearer ${HARNESSROUTER_API_KEY:?}\" \\\n  -H \"content-type: application/json\" \\\n  -d '{\n    \"input\": \"Reply with exactly: it works.\",\n    \"metadata\": {\"harness_id\": \"hermes\"},\n    \"model\": \"gpt-5.4-mini\",\n    \"stream\": false\n  }'\n```\n\nAs depicted above, the application keeps the same endpoint and event format. The same client can also continue sessions, retrieve files, and cancel work.\n![](https://substackcdn.com/image/fetch/$s_!npZV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c41213-9ed0-4ecb-8965-a4b5c4415816_2752x1536.jpeg)\n#### Session and security rules\nThe Unified Harness Protocol (UHP) standardizes the task lifecycle, but it does not make the harnesses behave the same. Different runtimes can choose different plans, tools, files, and models. The protocol gives the product one way to submit the work and inspect the result.\nThe local deployment also has a clear isolation limit. Sessions use separate operating-system users and workspaces. They do not run in separate containers. The Runner keeps the permissions needed to create those users, while each harness process runs as its assigned session user.\n![](https://substackcdn.com/image/fetch/$s_!lEY_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7aa0e8e5-8ebb-4ad7-8e15-2e4a4f3ad0e7_2752x1536.jpeg)\nProvider credentials should stay outside environments that agent tools can read. Application API keys should never reach browser code. A deployment outside loopback also needs TLS and the controls described in the UHP security specification.\n![](https://substackcdn.com/image/fetch/$s_!UmZK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c844f2d-58a7-4eab-9a09-d59ed2ea144b_2604x1108.jpeg)\n* * *\nThe two API calls above show why this matters when an agent becomes part of a product. Users may want to run a task with Codex, Claude Code, or Hermes.\nWithout a shared task interface, supporting each harness means writing another integration for progress, sessions, files, and cancellation.\nHarnessRouter lets the product offer that choice in its own UI.\nIt sends the task through UHP, selects the harness, and receives the result through the same API.\nThe team can test those workflows locally before putting them in front of users. As harnesses change, the product has a way to support more of them without rebuilding its task flow each time.\nHarnessRouter is Apache 2.0 licensed. The repository contains the self-hosted implementation, UHP schemas, and conformance tests.\nGitHub Repo: [**github.com/HarnessRouter/harnessrouter**](https://github.com/HarnessRouter/harnessrouter?ref=dailydoseofds.com).\n(don’t forget to star it ⭐️)\nGood day!\nPublished on Sep 23, 2026 \nComments \nShare \nCopy link [ Share to X ](https://x.com/intent/tweet?url=https%3A%2F%2Fwww.dailydoseofds.com%2Fp%2Frun-any-agent-harness-under-one-interface%2F&text=Run%20any%20agent%20harness%20under%20one%20interface) [ Share to Facebook ](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fwww.dailydoseofds.com%2Fp%2Frun-any-agent-harness-under-one-interface%2F) [ Share to Linkedin ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fwww.dailydoseofds.com%2Fp%2Frun-any-agent-harness-under-one-interface%2F)\nCopied \n[ Previous  Jev, Clearly Explained  ](https://www.dailydoseofds.com/p/jev-clearly-explained/) [ Next  Agent Harness with LangChain Middleware and Jev  ](https://www.dailydoseofds.com/ai-agents-with-langgraph-course-part-3-with-implementation/)\n[ ![Daily Dose of Data Science](https://storage.ghost.io/c/3f/df/3fdf6ed2-17ac-4b12-a693-8078bd13e748/content/images/2025/12/dailyds-logo-transparent-1.png) ](https://www.dailydoseofds.com)\nA daily column with insights, observations, tutorials and best practices on python and data science. Read by industry professionals at big tech, startups, and engineering students. \n  * Menu \n  * [ Contact ](https://www.dailydoseofds.com/contact/)\n  * [ FAQ ](https://www.dailydoseofds.com/faq/)\n\n\n[Daily Dose of Data Science](https://www.dailydoseofds.com) © 2026 \n[ ](https://x.com/_avichawla \"X \\(Formerly Twitter\\)\")\n",
  "body_base_path": "attachments/c067df749b61/pages/",
  "body_markdown_path": "attachments/c067df749b61/pages/archived-body.md",
  "local_html": "attachments/c067df749b61/pages/archived-body.html",
  "body_source": "prior_capture"
}