Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Ai Agent

ASecurity

Write, wire and test an in-process AI agent with @guren/plugin-ai (an Agent class that calls a language model and reaches the app through its .agent() routes). Use when the user asks to "add an AI feature", "call Claude/OpenAI from the app", "summarize/classify/triage with an LLM", "make an AI agent", "add a chat", or mentions app/Ai/Agents, config/ai.ts, appTools(), fakeAi() or make:ai-agent. Not for durable Workers agents (make:agent) or for exposing routes to external agents (agent-interfa...

29 stars
0 votes
0 copies
0 views
Added 9/23/2026
ai-agentstypescriptrustbashapi

Works with

cliapimcp

Security Analysis

A100/100

Scanned 9/23/2026

Install to Claude Code

$npx -y skills add gurenjs/guren --skill ai-agent --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Ai Agent?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Ai Agent
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/gurenjs-ai-agent/badge)](https://www.skillsdirectory.com/skills/gurenjs-ai-agent)

More formats (shields.io, HTML) on the badges page.

Download with Pro
Files
SKILL.md
---
name: ai-agent
description: Write, wire and test an in-process AI agent with @guren/plugin-ai (an Agent class that calls a language model and reaches the app through its .agent() routes). Use when the user asks to "add an AI feature", "call Claude/OpenAI from the app", "summarize/classify/triage with an LLM", "make an AI agent", "add a chat", or mentions app/Ai/Agents, config/ai.ts, appTools(), fakeAi() or make:ai-agent. Not for durable Workers agents (make:agent) or for exposing routes to external agents (agent-interface).
---

# AI Agent Skill

An in-process agent is a class under `app/Ai/Agents` that calls a model configured in `config/ai.ts`. It reaches the application **only** through `appTools()`, which turns the app's `.agent()` routes into model tools and runs every call through the same pipeline as the MCP endpoint: scopes, the route's validation and policies, approvals, and the audit trail. Nothing about a route is written twice.

## Setup (once per app)

```bash
bunx guren add ai                       # config/ai.ts, the key in config/env.ts, aiPlugin(), conversation tables
bunx guren add ai --provider openai     # or gateway
```

It needs `config/env.ts`. The key is optional: the app boots without it and the first prompt fails. Do not remove the `if (!env.ANTHROPIC_API_KEY) throw` guard in `config/ai.ts`; without a key the provider SDK reads `process.env` and sends a blank key.

## Writing an agent

```bash
bunx guren make:ai-agent TicketDigest --tools tickets_index --output --test
```

`--tools` fails if no route derives a name, so expose the route first (the `agent-interface` skill). Then check the generated class:

```typescript
import { Agent, Output } from '@guren/plugin-ai'
import { z } from 'zod'

export class TicketDigest extends Agent<typeof TicketDigest.scopes> {
  static override agentName = 'ticket-digest'
  static override scopes = ['tool:tickets_index'] as const

  instructions = 'You write a short digest of the open support tickets for an operator.'
  output = Output.object({ schema: z.object({ summary: z.string() }) })

  override tools() {
    return this.appTools(['tickets_index'])
  }
}
```

Rules:

- **Keep `static agentName` pinned.** Fakes, audit lines, queued runs and stored conversations key on it; the class-name default changes under a minifier.
- **Scopes are `tool:<name>` entries**, one per tool. `tools:read`, `tools:*` and `tools:<prefix>.*` grow silently as routes gain `.agent()`, and a prefix only matches dotted names.
- **Keep `Agent<typeof X.scopes>` with `scopes ... as const`.** That type parameter is what makes an ungranted `appTools()` name a compile error. Run `bunx guren codegen` so `.guren/agents.gen.ts` types the names.
- **Tool names must match `[A-Za-z0-9_-]{1,64}`.** Anthropic and OpenAI reject `tickets.index`; set `agent: { toolName: 'tickets_index' }` on the route.
- **Prefer `appTools()` over a local `tool()`.** A local tool runs with its closure's authority: no scope, policy, approval or audit applies. Use one only for work no route does, and never for a Model write a route already performs.

## Calling it

```typescript
const user = await this.auth.userOrFail<{ id: number }>()   // a type argument with id; the default Authenticatable does not fit as()
const response = await this.make('ai').agent(TicketDigest).as(user).prompt('...')
response.output   // typed from `output`; response.text, steps, usage, finishReason
```

- `as(user)` makes every tool call a request as that user, so the route's policies decide. `as(null)` allows read-only tools only and fails at `as()` otherwise.
- Tool results are untrusted model input (a ticket body can carry instructions). The consequential action must be a gated route, never a local tool.
- Conversations: `prompt(input, { conversation: true })` starts one and returns `conversationId`; `.continue(id)` resumes it. Nothing is stored without asking. The tables hold transcripts as the model saw them: sensitive data.
- Chat: `.stream(message, { conversation: conversation ?? true, signal: this.request.raw.signal })` after `validateBody(ChatTurnSchema)`, with `createChatTransport()` from `@guren/plugin-ai/client` in the page. An agent with `output` cannot stream.
- Background: `.queue(input)` needs `aiPlugin({ agents: [TicketDigest] })`, a queue binding and `bunx guren queue:work`; listen for `AgentResponded`. A run is attempted once. `.broadcast(input, channel)` streams the same run to a broadcast channel as `AGENT_CHUNK_EVENT`; make that channel private, since publishing is not authorized.

## Test it with the fake, first

```typescript
using ai = app.fakeAi()   // app = await TestApp.fromApp(realApp)
ai.respond(TicketDigest, [
  { toolCalls: [{ name: 'tickets_index', input: { status: 'open' } }], then: { output: { summary: 'One fire.' } } },
])
// drive the route or call the agent, then:
ai.assertPrompted(TicketDigest, (input) => input.includes('digest'))
expect(ai.calls(TicketDigest)[0]!.toolCalls[0]?.output).toBeDefined()   // the real route's answer
```

- Only the model is scripted. Tool calls hit the real routes, so the test proves scopes, policies and approvals are wired. Never stub the tools.
- An unscripted prompt fails the test when `ai` is disposed, naming the agent, even if the route turned the error into a 500.
- Mutation-check: bind the agent `as(null)` or drop the scope and confirm the test fails.

A passing fake test proves wiring, not answer quality. Do not claim an agent "works well" from fake tests alone, and never call a real provider from `bun test` or CI. Answer quality is measured by an eval: `defineEval()` in `tests/evals/<flow>.eval.ts` and `bunx guren ai:eval <flow>`, which calls the real model, costs money, and is never part of `guren check` or `guren gate`. Run it when asked, with `--dry-run` first.

Full guide: `docs/en/guides/ai-agents.md` (or `docs/ja/guides/ai-agents.md`) in the Guren framework repo. Routing reference: `__RULES_DIR__/routes-codegen.md`.

Attribution

gurenjsgurenjs
View sourceMore from gurenjs →
SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Related Skills

Caveman

Ultra-compressed communication mode that cuts output tokens while keeping technical accuracy. Levels: lite, full, ultra and the wenyan variants. Use for /caveman, "caveman mode", "talk like caveman", "be brief" or "less tokens".

1066601 votes

Hyperplan

Adversarial multi-agent planning skill. Self-orchestrates 5 hostile category members (unspecified-low, unspecified-high, deep, ultrabrain, artistry) via team-mode for ruthless cross-critique debate, distills only the defensible insights, then MANDATORILY hands the distilled insight bundle to the `plan` agent for executable plan formalization. Use when planning needs maximum rigor and surfacing of weak assumptions, blind spots, and over-engineering. Triggers: 'hyperplan', 'hpp', '/hyperplan', ...

686011 votes

Mcp Code Execution

Routes multi-tool workflows through MCP servers for large datasets and pipelines. Use when Bash tool overhead is limiting throughput on data-heavy tasks.

3351 votes

catchup

Recovers the conversation and failed tool calls of a previous Codex, Claude Code, Antigravity, Cline, Copilot CLI, Cursor, DeepSeek Harness, Kimi, OpenCode, Pi Agent, or ZCode session. Use when the user says "catch up", "what did the last session do", "get me up to speed", "I switched agents", asks to recover/summarize a previous session before continuing, or asks to diagnose or report a catchup failure. Do NOT use for the current conversation, git history, or any non-agent log.

651 votes

math-skill

A comprehensive mathematical reasoning skill for AI assistants — handles arithmetic to research-level problems with rigorous step-by-step reasoning, systematic verification, and transparent uncertainty handling

381 votes
View all in ai-agents →