Skip to Content
Polyant is open source under AGPL-3.0 — star us on GitHub.
How-toConnect Claude Code or Codex

Connect Claude Code or Codex

On this page

Dev mode serves the tool files on your machine into a remote agent, for the length of a turn. The engine equips them as ordinary tools - the same Ajv validation, governance gates, audit records and conversation state as a deployed tool - but the code runs in a process you control, and is never persisted by the engine. That makes it the fastest way to write a tool with a coding agent: you ask Claude Code or Codex for a tool, save the file, and the next message to the agent already uses it.

This guide takes you from a running Polyant instance to an agent calling a tool you just wrote. It is a development path, not a deployment mechanism: when the tool is ready, it ships as part of a plugin.

Managed services. Dev mode is not part of the open-source distribution.

Prerequisites

  • A deployment run with Polyant managed services that you can reach, and its base URL (http://localhost:4000 for a local engine)
  • polyant-cli 0.9.0 on your PATH (Node.js 20 or newer); see Using a key with polyant-cli for the install command
  • An agent you can experiment with, in a workspace you administer
  • A platform administrator available for one step you cannot do yourself

Which credential does what

Four different things are called a key or a token around dev mode, and they are not interchangeable.

CredentialHeld byRole in this guide
Management keyAn automation, scoped to one organizationWhat the CLI authenticates with. Must carry agent.dev:write to issue a dev token.
Personal tokenA person, carrying their live standingWorks in place of a management key, if the person holds the same permission.
Dev tokenThe local runtimeAuthenticates the WebSocket session that serves your tools. Short-lived, shown once, never recoverable.
Agent keyAny caller talking to the agentAuthorizes a conversation with the agent. Grants nothing in the panel and has no part in opening a dev session.

Treat a dev token as a credential that executes code on your machine with the agent’s real context: a dev tool receives the plaintext of the secrets it declares. Never commit it, never log it, and never pass it on the command line - dev connect reads it from an environment variable or a file precisely because argv is visible in ps.

Step 1: Have dev mode granted

Availability is the intersection of two grants, both off by default:

  1. A platform administrator grants dev mode to the organization, from the Admin Console. This step accepts only a person’s session - no management key can perform it, by design.
  2. An organization administrator enables it for the workspace, from the workspace settings (or PUT /api/organizations/{org}/workspaces/{workspace}/dev-mode).

Either half missing, or either half later revoked, and the session closes. If the organization grant is the one missing, the CLI says so precisely:

dev mode is not available for this agent: its organization has not been granted dev mode - a platform admin grants it from the Admin Console

You can check both halves at once:

polyant-cli api GET /api/organizations/<org>/workspaces/<workspace>/dev-mode # {"grantedToOrg":true,"enabled":true}

Step 2: Get a management key that can issue the token

The permission behind the dev token is agent.dev:write. A management key cannot grant itself a permission it does not hold, so apikey create refuses:

Cannot grant permission(s) you do not hold: agent.dev:write

The first key with that permission is therefore created by a person, from Organization → API keys in the panel. Give it agent.dev:write, plus whatever the rest of your loop needs (agent:read, agent.tool:read, conversation:read). Confirm what you are holding:

polyant-cli whoami

Step 3: Point the CLI at the instance

polyant-cli reads polyant.yaml from the current directory only - it does not search parent directories. Put it in the tool project you are about to create, or export POLYANT_URL and POLYANT_KEY instead. Without either:

No polyant.yaml found and POLYANT_URL is unset. Create polyant.yaml, or set POLYANT_URL and POLYANT_KEY.

A minimal file, with the key read from an environment variable rather than stored:

default: local targets: local: baseUrl: http://localhost:4000 keyEnv: POLYANT_KEY_LOCAL

Every command below also needs an organization and a workspace. Pass --org and --workspace, or declare a context in polyant.yaml and select it with --context; otherwise the CLI stops with Missing required scope component "org".

Step 4: Issue the dev token

export POLYANT_DEV_TOKEN=$(polyant-cli --org <org> --workspace <workspace> \ dev token issue <agent-slug> --ttl-hours 4 --yes)

The token goes to stdout alone, so it can be captured directly; the warning that it is shown once goes to stderr. Issuing a token invalidates every previous one for that agent and closes a session connected with an older one.

Step 5: Scaffold the tool project

polyant-cli dev init ./my-tools --agent <agent-slug> --yes cd my-tools && npm install

The scaffold writes a package.json, a tsconfig.json and one example tool. The two dependencies are not decoration: your tool files are imported by a child process started with this project’s tsx, and a tool file’s import "@polyant-ai/plugin-sdk" resolves from this project’s node_modules. The SDK comes from a git tag rather than a registry.

Keep this project separate from the repository your coding agent is working in, or at least out of its commits - it exists to be thrown away.

Step 6: Hold the session open

polyant-cli --org <org> --workspace <workspace> dev connect <agent-slug> --watch

This is the one command in the CLI that never returns. On success:

connecting to ws://localhost:4000/dev-mode/socket (attempt 1) connected: session 63c624a4-…, engine 1.1.0-ee, serving 1 tool(s): local_echo watching /…/my-tools for changes

It reads the token from $POLYANT_DEV_TOKEN, or from --token-env <VAR>, or from --token-file <path|->. There is no --token flag.

Step 7: Write a tool from your coding agent

With --watch on, a saved file is picked up immediately. Ask Claude Code or Codex for a tool in tools/, and the session reports the new set:

tools reloaded: local_echo, repo_branch

A tool is a default-exported defineTool. Its parameters schema is static and must satisfy OpenAI strict mode - no .optional(), no .default(), no unbounded z.record(). A name that collides with a tool the agent already has replaces it for the session; a new name is added for the session only. Neither is written to the agent’s configuration.

A session can serve hook functions the same way. A hook that declares overrides replaces the code behind a hook the agent already has, keeping that hook’s event, order and timeout, and its executions are still recorded under the canonical function name. A hook that declares bindTo runs on an event of your choosing for the session only: it is never saved to the agent’s hooks, and its name must be bare, without a plugin namespace. See Dev mode → Hooks served by a session.

Step 8: Watch the agent call it

polyant-cli --org <org> --workspace <workspace> \ agent chat <agent-slug> --message "Call repo_branch with path /path/to/checkout"

Reply text goes to stdout; steps and tool calls go to stderr:

· step 0 (initial) · tool repo_branch {"path":"/…/pleco"} · tool tooluse_… returned · step 0 finished (tool-calls) The current branch for the repository at the specified path is `explore-issue-triage-2026`.

The branch name is the proof: that string exists only on the machine running dev connect.

Claude Code

dev connect does not terminate, so it does not belong inside a turn of your coding session. Run it in a second terminal, or start it in the background and let the agent read its log - the agent writes tool files, the session reloads them, and nothing in the loop needs the agent’s attention.

In a default Claude Code setup the WebSocket to the engine opens with no extra configuration - this guide was written from one, against a local engine. What you do want to configure is the permission side: the session will run npm install, polyant-cli and git in the tool project, and each of those is a prompt unless allowed.

Codex

Codex sandboxes the commands it runs, and the sandbox blocks network access by default - which is exactly what dev connect needs. The failure is silent in the sense that it looks like the engine is down:

codex sandbox -- curl -s -o /dev/null -w '%{http_code}\n' http://localhost:4000/health # 000 codex sandbox -c sandbox_mode="workspace-write" \ -c sandbox_workspace_write.network_access=true \ -- curl -s -o /dev/null -w '%{http_code}\n' http://localhost:4000/health # 200

Note that the network flag alone is not enough: the sandbox has to be in workspace-write as well, because the read-only default keeps the network closed whatever the flag says. For an interactive session, put both in ~/.codex/config.toml.

The simpler answer, and the one that works for both tools, is to keep dev connect outside the coding agent entirely - in your own terminal, where no sandbox applies.

When it is working

polyant-cli --org <org> --workspace <workspace> dev token status <agent-slug>
session: e7f31f46-… connected: 2026-09-16T12:31:18.438Z tools: local_echo, repo_branch overrides: -

The agent’s Dev mode section shows the same thing, and each proxied call is audited with its dev-session provenance: the devSessionId is on the audit rows and on the reply, which the conversation and the Playground badge. Opening and closing the session are recorded in the organization’s management audit as dev_session.open and dev_session.close. If the engine restarts underneath you, the client reconnects on its own and the session id changes - the tool set is served again from the same files.

When it is not

What you seeWhat it means
dev mode is not available for this agent: its organization has not been granted dev modeStep 1, first half. A platform administrator has to act.
dev session refused: the token is missing, unknown, revoked or expired, dev mode is not available for this agent, or no agent with this slug existsDeliberately one generic refusal: the handshake never reveals which of those is true. Issue a new token and reconnect.
Cannot grant permission(s) you do not hold: agent.dev:writeStep 2. The key you are holding cannot mint a key stronger than itself.
Missing required scope component "org"No --org/--workspace and no selected context.
No polyant.yaml found and POLYANT_URL is unsetYou are not in the directory that holds the config.
disconnected: dev token revoked - retrying in 500msSomeone revoked the token, or issued a new one for the same agent. The client then retries and gets the generic refusal above.
Received network error or non-101 status codeThe engine is not reachable at that URL - or you are inside a sandbox that blocks it.
The agent answers without using your toolThe session is connected to a different agent, or the model simply chose not to call it. Check dev token status first.

Limits worth knowing

A dev session lives in memory on one engine node. With more than one replica, turns served by the others equip no dev tools, and the behaviour looks intermittent rather than broken.

A timed-out or cancelled invocation can still finish locally after the engine has discarded its result, so a tool that writes anywhere needs an idempotency key. State and audit writes returned with a failed call are not committed.

Opening a session is an administrator-level act, not a preview of what the agent is allowed to do: dev tools bypass the agent’s equipped tool list on purpose.

Clean up

polyant-cli --org <org> --workspace <workspace> dev token revoke <agent-slug> --yes --confirm <agent-slug>

Revocation closes the live session and remains possible even after a grant has been removed, so a stale credential can always be cleaned up. Delete the management key too, if it was made for this.

Last updated on