agent-interfacelisted
Install: claude install-skill gurenjs/guren
# Agent Interface Skill
Guren derives agent tools from the contracts a route already carries — its schemas, its model bindings, its authorization. Nothing is written twice: **there is no tool class and no second JSON schema to hand-write.** Your whole job is deciding which routes to expose and making sure the contracts they already have are complete.
## Exposing a route
Declare `agent` metadata on the route. Either form works:
```typescript
import { Router } from '@guren/core'
router.post('/posts', {
name: 'posts.store',
body: CreatePostSchema,
output: PostOutputSchema,
agent: { description: 'Create a blog post as the authenticated user.' },
}, [PostController, 'store'])
router
.post('/posts', { body: CreatePostSchema }, [PostController, 'store'])
.name('posts.store')
.agent({ description: 'Create a blog post as the authenticated user.' })
```
**Argument order trap:** the options object is the **second** argument and the handler is the **last** — `router.post(path, options, handler)`. Writing `router.post(path, handler, options)` registers the options object as the handler. The router recognizes an options object by its keys, `agent` included, so an object carrying only `agent` is still options and not a handler.
**One declaration per route.** Declaring `agent` in the route options *and* chaining `.agent()` throws at registration ("already carries agent metadata"). It is a refusal rather than a merge on purpose: a silent overwrite would drop security-rel