# Agent Discovery
Source: https://dorkos.ai/docs/guides/agent-discovery

Find your agent projects and coordinate them from one place with Mesh





# Agent Discovery [#agent-discovery]

<ProductShot id="agent-discovery" alt="The Mesh tab scanning for agent projects and registering them one by one into a growing network view" />

Mesh is DorkOS's agent discovery system. It scans your computer for AI agent projects (Claude Code, Cursor, Codex, and others), registers each one with a short profile called a manifest, and shows them all in one place: the Mesh tab.

If you run more than one agent across more than one project, Mesh is how you stop losing track of them.

## Try it [#try-it]

<Steps>
  <Step>
    **Open the Mesh tab.** You'll see a list of any agents already registered, plus a network view once you have a few.
  </Step>

  <Step>
    **Click "Scan for Agents."** Mesh walks your project folders looking for markers like `CLAUDE.md`, `AGENTS.md`, or a `.cursor/` folder. It reads files, it doesn't touch anything, so scanning is safe to run as often as you like.
  </Step>

  <Step>
    **Approve or deny each candidate.** Every project Mesh finds shows up as a card with an approve and a deny button. Approve the ones you want tracked. Deny the rest, and Mesh won't ask about them again.
  </Step>

  <Step>
    **Check the topology graph.** Approved agents appear as nodes, grouped by project. This is the fastest way to see everything you're running at a glance.
  </Step>
</Steps>

<Callout type="info">
  Scanning again later only shows new candidates. Agents you already approved or denied won't
  reappear.
</Callout>

### What if a scan finds nothing? [#what-if-a-scan-finds-nothing]

That usually means Mesh hasn't been pointed at the right folder yet. Check that your project has one of the marker files listed in [Discovering agents](#discovering-agents), or add the folder to your scan roots (see [Reference](#reference) below).

### What if I scan the same project twice? [#what-if-i-scan-the-same-project-twice]

Nothing bad happens. Mesh recognizes it's already registered and skips it silently.

## Denying agents [#denying-agents]

Not every project Mesh finds is one you want tracked, maybe it's an old experiment or a folder you keep around for reference. Click deny on its card, or give a reason if you want to remember why later. Denied projects won't show up in future scans. Changed your mind? You can remove a denial from the reference API below.

## Health states [#health-states]

Once an agent is registered, Mesh watches for signs of life:

* **Active**: seen in the last 5 minutes.
* **Inactive**: no signal for a while, but still within 24 hours.
* **Stale**: hasn't checked in for over 24 hours. It might be offline, or it might just be heads-down on something long-running.

## What "registering" actually does [#what-registering-actually-does]

When you approve an agent, DorkOS writes a small manifest describing it (name, what it does, which runtime it uses) and, if you have [Relay](/docs/concepts/relay) set up, gives it a messaging address so other agents can reach it. This multi-agent coordination is newer territory for DorkOS, so treat it as something to try, not something to depend on for anything critical yet.

## Reference [#reference]

The rest of this page is for scripting registration, building an integration, or understanding the internals. If you're just using the Mesh tab, you're done.

### Two registries: installed vs. discovered [#two-registries-installed-vs-discovered]

DorkOS keeps two separate lists of agents. They answer different questions, so don't conflate them.

| Registry                  | Where agents live                                                  | Who populates it                        | Scanner                                                     | API                              |
| ------------------------- | ------------------------------------------------------------------ | --------------------------------------- | ----------------------------------------------------------- | -------------------------------- |
| **Marketplace-installed** | `~/.dork/plugins/*` and `~/.dork/agents/*`                         | The marketplace install pipeline        | `apps/server/src/services/marketplace/installed-scanner.ts` | `GET /api/marketplace/installed` |
| **Mesh-discovered**       | Any directory you scan, typically project folders anywhere on disk | You, via scan from UI / MCP / CLI / API | `packages/mesh/src/discovery/unified-scanner.ts`            | `GET /api/mesh/agents`           |

* **"What did I install from the marketplace?"** → `GET /api/marketplace/installed`. Narrow provenance question: packages that came through the managed install pipeline with their `.dork/install-metadata.json` sidecar intact.
* **"What agents does my system know about right now?"** → `GET /api/mesh/agents`. The full fleet: every directory with a `.dork/agent.json` manifest that Mesh has been pointed at, whether via marketplace install, manual registration, or a discovery scan.

Marketplace installs always land under `~/.dork/{plugins,agents}/` with provenance metadata, so they also show up in the mesh registry once the install hands off. The reverse isn't true: a mesh-discovered agent registered from a directory the marketplace never touched has no install-metadata sidecar, so the installed-scanner ignores it.

### Where agents can live [#where-agents-can-live]

Any directory with a `.dork/agent.json` file is a valid agent location. You're not restricted to `~/.dork/agents/`:

* **Marketplace installs** → `~/.dork/agents/<name>/.dork/agent.json`, managed by the install pipeline.
* **Project-local agents** → `<your-project>/.dork/agent.json`, useful when an agent is version-controlled alongside the code it maintains.
* **Arbitrary locations** → any absolute path in `mesh.scanRoots` in `~/.dork/config.json`, or passed explicitly to `mesh_discover`.

### Discovery is pull-based [#discovery-is-pull-based]

Mesh doesn't watch your filesystem for new `.dork/agent.json` files. Discovery only runs when triggered:

* Clicking "Scan for Agents" in the UI.
* Calling `POST /api/mesh/discover` or the `mesh_discover` MCP tool.
* On startup, a background reconciler walks every path in `mesh.scanRoots` (configured in `config.json`) and picks up any manifests added since the last scan.

If you drop a new `.dork/agent.json` file into a directory Mesh has never walked, it stays invisible until a scan reaches that directory. This is deliberate: filesystem watchers are expensive and noisy, and pull-based discovery gives you deterministic control over when the registry changes.

Manifest write-through semantics (the file on disk is authoritative, the SQLite registry is a derived cache) are covered by the [`agent-storage` contributor rule](https://github.com/dork-labs/dorkos/blob/main/.claude/rules/agent-storage.md) and [ADR-0043](https://github.com/dork-labs/dorkos/blob/main/decisions/).

### Discovering agents [#discovering-agents]

Mesh ships with ten detection strategies covering the major AI coding agents:

| Strategy        | Filesystem markers                                                                                   | Runtime       |
| --------------- | ---------------------------------------------------------------------------------------------------- | ------------- |
| **claude-code** | `CLAUDE.md` or `AGENTS.md` at the project root. Extracts a description from the first paragraph.     | `claude-code` |
| **cursor**      | `.cursor/` directory or `.cursorrules` file at the project root.                                     | `cursor`      |
| **codex**       | `.codex/` directory at the project root.                                                             | `codex`       |
| **windsurf**    | `.windsurfrules` file or `.windsurf/` directory at the project root.                                 | `windsurf`    |
| **gemini**      | `GEMINI.md` file or `.gemini/` directory at the project root.                                        | `gemini`      |
| **cline**       | `.clinerules` file or directory at the project root.                                                 | `cline`       |
| **roo-code**    | `.roo/` directory or `.roorules` file at the project root.                                           | `roo-code`    |
| **copilot**     | Copilot-specific files within `.github/` (`copilot-instructions.md`, `instructions/`, or `agents/`). | `copilot`     |
| **amazon-q**    | `.amazonq/` directory at the project root.                                                           | `amazon-q`    |
| **continue**    | `.continue/` directory at the project root.                                                          | `continue`    |

The `AgentRuntime` enum also includes placeholder values for agents that don't yet have detection strategies: `augment`, `jetbrains-ai`, `kilo-code`, `trae`, and `other`.

Any directory that already contains a `.dork/agent.json` manifest is auto-imported: the agent is added to the registry without requiring approval again.

Trigger a scan from the UI by opening the Mesh tab and clicking the discover button, or use the REST API:

```bash
curl -X POST http://localhost:4242/api/mesh/discover \
  -H "Content-Type: application/json" \
  -d '{ "roots": ["/home/user/projects"], "maxDepth": 5 }'
```

The response is an array of `DiscoveryCandidate` objects, each containing the directory path, the strategy that matched, and hints about the agent's name and capabilities. In the UI, each candidate appears as a card with approve and deny buttons.

<Callout type="info">
  Discovery is non-destructive. It only reads filesystem markers and never modifies your project
  directories until you explicitly approve a registration.
</Callout>

Subsequent scans automatically skip directories that are already registered or denied, and silently re-import agents that have a `.dork/agent.json` manifest from a previous session.

### Agent manifests [#agent-manifests]

Every registered agent has a manifest describing its identity and configuration. It's stored both in the Mesh SQLite database and as a `.dork/agent.json` file in the agent's project directory.

```json
{
  "id": "01HXYZ...",
  "name": "grep-whisperer",
  "description": "Handles web research and summarization tasks",
  "runtime": "claude-code",
  "capabilities": ["web-search", "summarization"],
  "behavior": { "responseMode": "always" },
  "namespace": "research",
  "registeredAt": "2026-02-26T12:00:00Z",
  "registeredBy": "dorkos-ui"
}
```

<TypeTable
  type="{
  id: { type: 'string', description: 'ULID assigned at registration (unique, time-ordered)' },
  name: {
    type: 'string',
    description: &#x22;Human-readable agent name (e.g., 'backend-api', 'frontend-ui')&#x22;,
  },
  description: { type: 'string', description: 'What the agent does', default: &#x22;''&#x22; },
  runtime: {
    type: &#x22;'claude-code' | 'cursor' | 'codex' | 'other'&#x22;,
    description: 'The AI platform powering the agent',
  },
  capabilities: {
    type: 'string[]',
    description:
      &#x22;Capability tags that describe what the agent can do (e.g., 'typescript', 'testing')&#x22;,
    default: '[]',
  },
  behavior: {
    type: 'AgentBehavior',
    description: &#x22;Response mode: 'always', 'direct-only', 'mention-only', or 'silent'&#x22;,
    default: &#x22;{ responseMode: 'always' }&#x22;,
  },
  namespace: {
    type: 'string',
    description:
      'Derived from project path relative to scan root, used for topology grouping and access control',
  },
  registeredAt: { type: 'string', description: 'ISO 8601 timestamp of registration' },
  registeredBy: { type: 'string', description: 'Identifier of who or what registered the agent' },
}"
/>

Discovery strategies automatically populate the manifest with hints extracted from the project (name from `package.json` or directory name, capabilities from detected tooling), but you can override any field during registration.

### Registering agents [#registering-agents]

There are three ways to register an agent in Mesh.

**MeshPanel UI.** Open the Mesh tab and click "Register Agent." The form lets you enter the agent name, capabilities, project path, and optional metadata. You can also accept a discovery candidate directly from its card.

**REST API.** Send a POST request with the agent manifest:

```bash
curl -X POST http://localhost:4242/api/mesh/agents \
  -H "Content-Type: application/json" \
  -d '{
    "path": "/home/user/projects/research",
    "overrides": {
      "name": "research-agent",
      "runtime": "claude-code",
      "capabilities": ["web-search", "summarization"]
    }
  }'
```

**MCP tools.** Agents can discover and register other agents using the mesh MCP tools.

Scan for candidates:

```
mesh_discover({ roots: ["/home/user/projects"], maxDepth: 5 })
```

By default this returns only unregistered candidates. Pass `includeRegistered: true` to also see agents auto-imported during the scan (directories with an existing `.dork/agent.json`):

```
mesh_discover({ roots: ["/home/user/projects"], includeRegistered: true })
```

Register an agent directly:

```
mesh_register({ path: "/home/user/projects/research", name: "research-agent", runtime: "claude-code", capabilities: ["web-search"] })
```

When an agent creates a registration via MCP tools, the manifest is written to `.dork/agent.json` in the project directory and the agent becomes available in the registry right away.

<Callout type="info">
  When Relay is enabled, registering an agent also creates a messaging address for it at
  `relay.agent.{namespace}.{agentId}`. Multi-agent messaging through Relay is still an early,
  unverified path end-to-end, so test your setup before relying on it.
</Callout>

### Network topology [#network-topology]

The topology graph in the Mesh tab renders your agent network visually. Agents appear as nodes grouped by namespace, with namespace hub nodes connecting related agents. Cross-namespace edges show permitted communication paths.

Live health data is overlaid on the graph:

* **Active nodes**: seen recently (within the last 5 minutes).
* **Inactive nodes**: not seen for a while, but within 24 hours.
* **Stale nodes**: not seen for over 24 hours, may be offline.

The stats header above the graph shows aggregate counts: total agents, agents by health state, and agents by runtime type.

### Health monitoring [#health-monitoring]

Mesh tracks agent health through a heartbeat protocol. Agents send periodic heartbeats to signal they're alive and working.

```bash
curl -X POST http://localhost:4242/api/mesh/agents/{agentId}/heartbeat \
  -H "Content-Type: application/json" \
  -d '{ "event": "processing-task" }'
```

<TypeTable
  type="{
  active: { type: 'status', description: 'Agent has been seen within the last 5 minutes' },
  inactive: { type: 'status', description: 'Agent has not been seen for up to 24 hours' },
  stale: {
    type: 'status',
    description: 'Agent has not been seen for over 24 hours and may be offline',
  },
}"
/>

When an agent's health state changes, Mesh emits a lifecycle event through the Relay signal system. The per-agent detail view shows the current state, last seen timestamp, last event, and capabilities.

### Denying agents (API) [#denying-agents-api]

Deny a candidate via the UI (click the deny button on its card) or the API:

```bash
curl -X POST http://localhost:4242/api/mesh/deny \
  -H "Content-Type: application/json" \
  -d '{ "path": "/home/user/projects/legacy-bot", "reason": "Deprecated project" }'
```

Denied paths are stored in the SQLite database and checked during every scan. The candidate won't appear in future discovery results.

View the denial list and remove entries if you change your mind:

```bash
# List denied paths
curl http://localhost:4242/api/mesh/denied

# Remove a denial (re-enables discovery for that path, path is URL-encoded)
curl -X DELETE "http://localhost:4242/api/mesh/denied/%2Fhome%2Fuser%2Fprojects%2Flegacy-bot"
```

### Configuration [#configuration]

<TypeTable
  type="{
  'Discovery roots': {
    type: 'string[]',
    description: 'Directories to scan for agents (passed in the POST /discover request body)',
  },
  'Max scan depth': {
    type: 'number',
    description: 'How many directory levels deep to scan',
    default: '3',
  },
}"
/>

Mesh data is stored in the consolidated DorkOS database at `~/.dork/dork.db` (managed by Drizzle ORM). Agent manifests are also written to `.dork/agent.json` in each registered agent's project directory as a portable backup that survives database rebuilds.

## Next steps [#next-steps]

<Cards>
  <Card title="Mesh Concepts" href="/docs/concepts/mesh">
    Understand the architecture behind agent discovery, namespaces, and topology.
  </Card>

  <Card title="Relay Messaging" href="/docs/guides/relay-messaging">
    Send messages between the agents you have registered.
  </Card>

  <Card title="Agent Coordination" href="/docs/guides/agent-coordination">
    Multi-agent workflow patterns using Relay and Mesh together.
  </Card>
</Cards>
