---
outline: deep
---

# DF8404: Agent Exposure Without Handler

## Message

> Command "`{id}`" declares agent exposure but has no handler

## Cause

`ctx.commands.register(command)` or a command handle `update()` received a command carrying an `agent` field but no `handler`. Agent-exposed commands are projected into `ctx.agent` as callable tools (reaching MCP clients through the devframe MCP adapter), so they must be executable server-side — a handler-less command is a palette group and cannot run.

## Example

```ts
// ✗ Bad: group-only command opting into the agent surface
ctx.commands.register({
  id: 'my-tool:group',
  title: 'My tool',
  agent: { description: 'Run my tool.' },
  children: [/* … */],
})

// ✓ Good: the executable child carries the agent field
ctx.commands.register({
  id: 'my-tool:group',
  title: 'My tool',
  children: [
    {
      id: 'my-tool:reload',
      title: 'Reload',
      agent: { description: 'Reload my tool\'s state. Call after changing its config.' },
      handler: () => reload(),
    },
  ],
})
```

## Fix

- Add a `handler` to the command carrying the `agent` field.
- Or move the `agent` field to an executable child command.

## Source

- [`packages/hub/src/node/host-commands.ts`](https://github.com/devframes/devframe/blob/main/packages/hub/src/node/host-commands.ts) — `DevframeCommandsHost.register()` and command handle `update()` validate agent exposure across the command tree.
