@frontmcp/skills 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +135 -0
- package/catalog/TEMPLATE.md +49 -0
- package/catalog/adapters/create-adapter/SKILL.md +127 -0
- package/catalog/adapters/official-adapters/SKILL.md +136 -0
- package/catalog/auth/configure-auth/SKILL.md +250 -0
- package/catalog/auth/configure-auth/references/auth-modes.md +77 -0
- package/catalog/auth/configure-session/SKILL.md +201 -0
- package/catalog/config/configure-elicitation/SKILL.md +136 -0
- package/catalog/config/configure-http/SKILL.md +167 -0
- package/catalog/config/configure-throttle/SKILL.md +189 -0
- package/catalog/config/configure-throttle/references/guard-config.md +68 -0
- package/catalog/config/configure-transport/SKILL.md +151 -0
- package/catalog/config/configure-transport/references/protocol-presets.md +57 -0
- package/catalog/deployment/build-for-browser/SKILL.md +95 -0
- package/catalog/deployment/build-for-cli/SKILL.md +100 -0
- package/catalog/deployment/build-for-sdk/SKILL.md +218 -0
- package/catalog/deployment/deploy-to-cloudflare/SKILL.md +192 -0
- package/catalog/deployment/deploy-to-lambda/SKILL.md +304 -0
- package/catalog/deployment/deploy-to-node/SKILL.md +229 -0
- package/catalog/deployment/deploy-to-node/references/Dockerfile.example +45 -0
- package/catalog/deployment/deploy-to-vercel/SKILL.md +196 -0
- package/catalog/deployment/deploy-to-vercel/references/vercel.json.example +60 -0
- package/catalog/development/create-agent/SKILL.md +563 -0
- package/catalog/development/create-agent/references/llm-config.md +46 -0
- package/catalog/development/create-job/SKILL.md +566 -0
- package/catalog/development/create-prompt/SKILL.md +400 -0
- package/catalog/development/create-provider/SKILL.md +233 -0
- package/catalog/development/create-resource/SKILL.md +437 -0
- package/catalog/development/create-skill/SKILL.md +526 -0
- package/catalog/development/create-skill-with-tools/SKILL.md +579 -0
- package/catalog/development/create-tool/SKILL.md +418 -0
- package/catalog/development/create-tool/references/output-schema-types.md +56 -0
- package/catalog/development/create-tool/references/tool-annotations.md +34 -0
- package/catalog/development/create-workflow/SKILL.md +709 -0
- package/catalog/development/decorators-guide/SKILL.md +598 -0
- package/catalog/plugins/create-plugin/SKILL.md +336 -0
- package/catalog/plugins/create-plugin-hooks/SKILL.md +282 -0
- package/catalog/plugins/official-plugins/SKILL.md +667 -0
- package/catalog/setup/frontmcp-skills-usage/SKILL.md +200 -0
- package/catalog/setup/multi-app-composition/SKILL.md +358 -0
- package/catalog/setup/nx-workflow/SKILL.md +357 -0
- package/catalog/setup/project-structure-nx/SKILL.md +186 -0
- package/catalog/setup/project-structure-standalone/SKILL.md +153 -0
- package/catalog/setup/setup-project/SKILL.md +493 -0
- package/catalog/setup/setup-redis/SKILL.md +385 -0
- package/catalog/setup/setup-sqlite/SKILL.md +359 -0
- package/catalog/skills-manifest.json +414 -0
- package/catalog/testing/setup-testing/SKILL.md +539 -0
- package/catalog/testing/setup-testing/references/test-auth.md +88 -0
- package/catalog/testing/setup-testing/references/test-browser-build.md +57 -0
- package/catalog/testing/setup-testing/references/test-cli-binary.md +48 -0
- package/catalog/testing/setup-testing/references/test-direct-client.md +62 -0
- package/catalog/testing/setup-testing/references/test-e2e-handler.md +51 -0
- package/catalog/testing/setup-testing/references/test-tool-unit.md +41 -0
- package/package.json +34 -0
- package/src/index.d.ts +3 -0
- package/src/index.js +16 -0
- package/src/index.js.map +1 -0
- package/src/loader.d.ts +46 -0
- package/src/loader.js +75 -0
- package/src/loader.js.map +1 -0
- package/src/manifest.d.ts +81 -0
- package/src/manifest.js +26 -0
- package/src/manifest.js.map +1 -0
|
@@ -0,0 +1,563 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: create-agent
|
|
3
|
+
description: Create autonomous AI agents with inner tools, LLM providers, and multi-agent swarms. Use when building agents, configuring LLM adapters, adding inner tools, or setting up agent handoff.
|
|
4
|
+
tags: [agent, ai, llm, tools, autonomous]
|
|
5
|
+
parameters:
|
|
6
|
+
- name: llm-provider
|
|
7
|
+
description: LLM provider to use
|
|
8
|
+
type: string
|
|
9
|
+
default: anthropic
|
|
10
|
+
- name: name
|
|
11
|
+
description: Agent name
|
|
12
|
+
type: string
|
|
13
|
+
required: true
|
|
14
|
+
examples:
|
|
15
|
+
- scenario: Create a code review agent with GitHub tools
|
|
16
|
+
expected-outcome: Agent autonomously reviews PRs using inner tools
|
|
17
|
+
- scenario: Create a multi-agent swarm for complex workflows
|
|
18
|
+
expected-outcome: Agents hand off tasks to each other
|
|
19
|
+
priority: 8
|
|
20
|
+
visibility: both
|
|
21
|
+
license: Apache-2.0
|
|
22
|
+
metadata:
|
|
23
|
+
docs: https://docs.agentfront.dev/frontmcp/servers/agents
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
# Creating an Autonomous Agent
|
|
27
|
+
|
|
28
|
+
Agents are autonomous AI entities that use an LLM to reason, plan, and invoke inner tools to accomplish goals. In FrontMCP, agents are TypeScript classes that extend `AgentContext`, decorated with `@Agent`, and registered on a `@FrontMcp` server or inside an `@App`.
|
|
29
|
+
|
|
30
|
+
## When to Use @Agent vs @Tool
|
|
31
|
+
|
|
32
|
+
Use `@Agent` when the task requires autonomous reasoning, multi-step planning, or LLM-driven decision making. An agent receives a goal, decides which tools to call, interprets results, and iterates until the goal is met. Use `@Tool` when you need a direct, deterministic function that executes a single action without LLM involvement.
|
|
33
|
+
|
|
34
|
+
| Aspect | @Agent | @Tool |
|
|
35
|
+
| --------------- | ------------------------------- | ---------------------------- |
|
|
36
|
+
| Execution | Autonomous LLM loop | Direct function call |
|
|
37
|
+
| Decision making | LLM chooses what to do | Caller decides |
|
|
38
|
+
| Inner tools | Has its own tools it can invoke | No inner tools |
|
|
39
|
+
| Use case | Complex, multi-step workflows | Single, well-defined actions |
|
|
40
|
+
|
|
41
|
+
## Class-Based Pattern
|
|
42
|
+
|
|
43
|
+
Create a class extending `AgentContext<In, Out>` and optionally override the `execute(input: In): Promise<Out>` method. The `@Agent` decorator requires `name`, `description`, and `llm` configuration.
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
import { Agent, AgentContext } from '@frontmcp/sdk';
|
|
47
|
+
import { z } from 'zod';
|
|
48
|
+
|
|
49
|
+
@Agent({
|
|
50
|
+
name: 'code_reviewer',
|
|
51
|
+
description: 'Reviews code changes and provides feedback',
|
|
52
|
+
llm: {
|
|
53
|
+
adapter: 'anthropic',
|
|
54
|
+
model: 'claude-sonnet-4-20250514',
|
|
55
|
+
apiKey: { env: 'ANTHROPIC_API_KEY' },
|
|
56
|
+
},
|
|
57
|
+
inputSchema: {
|
|
58
|
+
diff: z.string().describe('The code diff to review'),
|
|
59
|
+
language: z.string().optional().describe('Programming language'),
|
|
60
|
+
},
|
|
61
|
+
systemInstructions: 'You are an expert code reviewer. Focus on correctness, performance, and maintainability.',
|
|
62
|
+
})
|
|
63
|
+
class CodeReviewerAgent extends AgentContext {
|
|
64
|
+
async execute(input: { diff: string; language?: string }) {
|
|
65
|
+
// Default behavior: runs the agent loop automatically
|
|
66
|
+
// The agent will use its LLM to analyze the diff and produce a review
|
|
67
|
+
return super.execute(input);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Available Context Methods and Properties
|
|
73
|
+
|
|
74
|
+
`AgentContext` extends `ExecutionContextBase`, which provides:
|
|
75
|
+
|
|
76
|
+
**Agent-Specific Methods:**
|
|
77
|
+
|
|
78
|
+
- `execute(input: In): Promise<Out>` -- the main method; default runs the agent loop
|
|
79
|
+
- `completion(prompt: AgentPrompt, options?): Promise<AgentCompletion>` -- make a single LLM call
|
|
80
|
+
- `streamCompletion(prompt: AgentPrompt, options?): AsyncIterable<AgentCompletionChunk>` -- stream an LLM response
|
|
81
|
+
- `executeTool(toolDef, input): Promise<unknown>` -- (protected) invoke one of the agent's inner tools programmatically
|
|
82
|
+
|
|
83
|
+
**Inherited Methods:**
|
|
84
|
+
|
|
85
|
+
- `this.get(token)` -- resolve a dependency from DI (throws if not found)
|
|
86
|
+
- `this.tryGet(token)` -- resolve a dependency from DI (returns `undefined` if not found)
|
|
87
|
+
- `this.fail(err)` -- abort execution, triggers error flow (never returns)
|
|
88
|
+
- `this.mark(stage)` -- set the active execution stage for debugging/tracking
|
|
89
|
+
- `this.fetch(input, init?)` -- HTTP fetch with context propagation
|
|
90
|
+
- `this.notify(message, level?)` -- send a log-level notification to the client
|
|
91
|
+
- `this.respondProgress(value, total?)` -- send a progress notification to the client
|
|
92
|
+
|
|
93
|
+
**Properties:**
|
|
94
|
+
|
|
95
|
+
- `this.input` -- the validated input object
|
|
96
|
+
- `this.output` -- the output (available after execute)
|
|
97
|
+
- `this.llmAdapter` -- the configured LLM adapter instance
|
|
98
|
+
- `this.toolDefinitions` -- definitions of inner tools available to the agent
|
|
99
|
+
- `this.toolExecutor` -- executor for invoking inner tools
|
|
100
|
+
- `this.metadata` -- agent metadata from the decorator
|
|
101
|
+
- `this.scope` -- the current scope instance
|
|
102
|
+
- `this.context` -- the execution context
|
|
103
|
+
|
|
104
|
+
## LLM Configuration
|
|
105
|
+
|
|
106
|
+
The `llm` field is required and configures which LLM provider and model the agent uses.
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
@Agent({
|
|
110
|
+
name: 'my_agent',
|
|
111
|
+
description: 'An agent with LLM config',
|
|
112
|
+
llm: {
|
|
113
|
+
adapter: 'anthropic', // 'anthropic' or 'openai'
|
|
114
|
+
model: 'claude-sonnet-4-20250514',
|
|
115
|
+
apiKey: { env: 'ANTHROPIC_API_KEY' }, // read from env var
|
|
116
|
+
},
|
|
117
|
+
})
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The `apiKey` field accepts either an object `{ env: 'ENV_VAR_NAME' }` to read from environment variables, or a string value directly (not recommended for production).
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
// OpenAI example
|
|
124
|
+
llm: {
|
|
125
|
+
adapter: 'openai',
|
|
126
|
+
model: 'gpt-4o',
|
|
127
|
+
apiKey: { env: 'OPENAI_API_KEY' },
|
|
128
|
+
},
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Custom execute() vs Default Agent Loop
|
|
132
|
+
|
|
133
|
+
By default, calling `execute()` runs the full agent loop: the LLM receives the input plus system instructions, decides which inner tools to call, processes results, and iterates until it produces a final answer.
|
|
134
|
+
|
|
135
|
+
Override `execute()` when you need custom orchestration logic:
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
@Agent({
|
|
139
|
+
name: 'structured_reviewer',
|
|
140
|
+
description: 'Reviews code with a structured multi-pass approach',
|
|
141
|
+
llm: {
|
|
142
|
+
adapter: 'anthropic',
|
|
143
|
+
model: 'claude-sonnet-4-20250514',
|
|
144
|
+
apiKey: { env: 'ANTHROPIC_API_KEY' },
|
|
145
|
+
},
|
|
146
|
+
inputSchema: {
|
|
147
|
+
code: z.string().describe('Source code to review'),
|
|
148
|
+
},
|
|
149
|
+
outputSchema: {
|
|
150
|
+
issues: z.array(
|
|
151
|
+
z.object({
|
|
152
|
+
severity: z.enum(['error', 'warning', 'info']),
|
|
153
|
+
line: z.number(),
|
|
154
|
+
message: z.string(),
|
|
155
|
+
}),
|
|
156
|
+
),
|
|
157
|
+
summary: z.string(),
|
|
158
|
+
},
|
|
159
|
+
})
|
|
160
|
+
class StructuredReviewerAgent extends AgentContext {
|
|
161
|
+
async execute(input: { code: string }) {
|
|
162
|
+
this.mark('security-pass');
|
|
163
|
+
const securityReview = await this.completion({
|
|
164
|
+
messages: [{ role: 'user', content: `Review this code for security issues:\n${input.code}` }],
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
this.mark('quality-pass');
|
|
168
|
+
const qualityReview = await this.completion({
|
|
169
|
+
messages: [{ role: 'user', content: `Review this code for quality issues:\n${input.code}` }],
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
this.mark('synthesis');
|
|
173
|
+
const finalReview = await this.completion({
|
|
174
|
+
messages: [
|
|
175
|
+
{
|
|
176
|
+
role: 'user',
|
|
177
|
+
content: `Combine these reviews into a structured report:\nSecurity: ${securityReview.content}\nQuality: ${qualityReview.content}`,
|
|
178
|
+
},
|
|
179
|
+
],
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
return JSON.parse(finalReview.content);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## completion() and streamCompletion()
|
|
188
|
+
|
|
189
|
+
Use `completion()` for a single LLM call that returns the full response, and `streamCompletion()` for streaming responses token by token.
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
@Agent({
|
|
193
|
+
name: 'summarizer',
|
|
194
|
+
description: 'Summarizes text using LLM',
|
|
195
|
+
llm: {
|
|
196
|
+
adapter: 'anthropic',
|
|
197
|
+
model: 'claude-sonnet-4-20250514',
|
|
198
|
+
apiKey: { env: 'ANTHROPIC_API_KEY' },
|
|
199
|
+
},
|
|
200
|
+
inputSchema: {
|
|
201
|
+
text: z.string().describe('Text to summarize'),
|
|
202
|
+
},
|
|
203
|
+
})
|
|
204
|
+
class SummarizerAgent extends AgentContext {
|
|
205
|
+
async execute(input: { text: string }) {
|
|
206
|
+
// Single completion call
|
|
207
|
+
const result = await this.completion(
|
|
208
|
+
{
|
|
209
|
+
messages: [{ role: 'user', content: `Summarize this text:\n${input.text}` }],
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
maxTokens: 500,
|
|
213
|
+
temperature: 0.3,
|
|
214
|
+
},
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
return result.content;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Streaming example:
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
async execute(input: { text: string }) {
|
|
226
|
+
const stream = this.streamCompletion({
|
|
227
|
+
messages: [{ role: 'user', content: `Analyze this text:\n${input.text}` }],
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
let fullResponse = '';
|
|
231
|
+
for await (const chunk of stream) {
|
|
232
|
+
fullResponse += chunk.delta;
|
|
233
|
+
await this.notify(`Processing: ${fullResponse.length} chars`, 'debug');
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return fullResponse;
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Inner Tools
|
|
241
|
+
|
|
242
|
+
The `tools` array in `@Agent` metadata defines tools that the agent itself can invoke during its reasoning loop. These are NOT exposed to external callers -- they are private to the agent.
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
import { Tool, ToolContext, Agent, AgentContext } from '@frontmcp/sdk';
|
|
246
|
+
import { z } from 'zod';
|
|
247
|
+
|
|
248
|
+
@Tool({
|
|
249
|
+
name: 'fetch_pr',
|
|
250
|
+
description: 'Fetch pull request details from GitHub',
|
|
251
|
+
inputSchema: {
|
|
252
|
+
owner: z.string(),
|
|
253
|
+
repo: z.string(),
|
|
254
|
+
number: z.number(),
|
|
255
|
+
},
|
|
256
|
+
})
|
|
257
|
+
class FetchPRTool extends ToolContext {
|
|
258
|
+
async execute(input: { owner: string; repo: string; number: number }) {
|
|
259
|
+
const response = await this.fetch(
|
|
260
|
+
`https://api.github.com/repos/${input.owner}/${input.repo}/pulls/${input.number}`,
|
|
261
|
+
);
|
|
262
|
+
return response.json();
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
@Tool({
|
|
267
|
+
name: 'post_review_comment',
|
|
268
|
+
description: 'Post a review comment on a PR',
|
|
269
|
+
inputSchema: {
|
|
270
|
+
owner: z.string(),
|
|
271
|
+
repo: z.string(),
|
|
272
|
+
number: z.number(),
|
|
273
|
+
body: z.string(),
|
|
274
|
+
},
|
|
275
|
+
})
|
|
276
|
+
class PostReviewCommentTool extends ToolContext {
|
|
277
|
+
async execute(input: { owner: string; repo: string; number: number; body: string }) {
|
|
278
|
+
await this.fetch(`https://api.github.com/repos/${input.owner}/${input.repo}/pulls/${input.number}/reviews`, {
|
|
279
|
+
method: 'POST',
|
|
280
|
+
body: JSON.stringify({ body: input.body, event: 'COMMENT' }),
|
|
281
|
+
});
|
|
282
|
+
return 'Comment posted';
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
@Agent({
|
|
287
|
+
name: 'pr_reviewer',
|
|
288
|
+
description: 'Autonomously reviews GitHub pull requests',
|
|
289
|
+
llm: {
|
|
290
|
+
adapter: 'anthropic',
|
|
291
|
+
model: 'claude-sonnet-4-20250514',
|
|
292
|
+
apiKey: { env: 'ANTHROPIC_API_KEY' },
|
|
293
|
+
},
|
|
294
|
+
inputSchema: {
|
|
295
|
+
owner: z.string().describe('Repository owner'),
|
|
296
|
+
repo: z.string().describe('Repository name'),
|
|
297
|
+
prNumber: z.number().describe('PR number to review'),
|
|
298
|
+
},
|
|
299
|
+
systemInstructions: 'You are a senior code reviewer. Fetch the PR, analyze changes, and post a thorough review.',
|
|
300
|
+
tools: [FetchPRTool, PostReviewCommentTool], // Inner tools the agent can use
|
|
301
|
+
})
|
|
302
|
+
class PRReviewerAgent extends AgentContext {
|
|
303
|
+
// Default execute() runs the agent loop.
|
|
304
|
+
// The agent will autonomously call FetchPRTool, analyze the diff,
|
|
305
|
+
// and call PostReviewCommentTool to leave a review.
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## Exported Tools
|
|
310
|
+
|
|
311
|
+
Use `exports: { tools: [] }` to expose specific tools that the agent makes available to external callers. Unlike inner tools (which the agent uses privately), exported tools appear in the MCP tool listing for clients to invoke directly.
|
|
312
|
+
|
|
313
|
+
```typescript
|
|
314
|
+
@Agent({
|
|
315
|
+
name: 'data_pipeline',
|
|
316
|
+
description: 'Data processing pipeline agent',
|
|
317
|
+
llm: {
|
|
318
|
+
adapter: 'openai',
|
|
319
|
+
model: 'gpt-4o',
|
|
320
|
+
apiKey: { env: 'OPENAI_API_KEY' },
|
|
321
|
+
},
|
|
322
|
+
tools: [ExtractTool, TransformTool, LoadTool], // Agent uses these internally
|
|
323
|
+
exports: { tools: [ValidateDataTool, StatusTool] }, // These are exposed to MCP clients
|
|
324
|
+
})
|
|
325
|
+
class DataPipelineAgent extends AgentContext {}
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## Nested Agents (Sub-Agents)
|
|
329
|
+
|
|
330
|
+
Use the `agents` array to compose agents from smaller, specialized sub-agents. Each sub-agent has its own LLM config, inner tools, and system instructions.
|
|
331
|
+
|
|
332
|
+
```typescript
|
|
333
|
+
@Agent({
|
|
334
|
+
name: 'security_auditor',
|
|
335
|
+
description: 'Audits code for security vulnerabilities',
|
|
336
|
+
llm: { adapter: 'anthropic', model: 'claude-sonnet-4-20250514', apiKey: { env: 'ANTHROPIC_API_KEY' } },
|
|
337
|
+
systemInstructions: 'Focus on OWASP Top 10 vulnerabilities.',
|
|
338
|
+
tools: [StaticAnalysisTool],
|
|
339
|
+
})
|
|
340
|
+
class SecurityAuditorAgent extends AgentContext {}
|
|
341
|
+
|
|
342
|
+
@Agent({
|
|
343
|
+
name: 'performance_auditor',
|
|
344
|
+
description: 'Audits code for performance issues',
|
|
345
|
+
llm: { adapter: 'anthropic', model: 'claude-sonnet-4-20250514', apiKey: { env: 'ANTHROPIC_API_KEY' } },
|
|
346
|
+
systemInstructions: 'Focus on time complexity, memory leaks, and N+1 queries.',
|
|
347
|
+
tools: [ProfilerTool],
|
|
348
|
+
})
|
|
349
|
+
class PerformanceAuditorAgent extends AgentContext {}
|
|
350
|
+
|
|
351
|
+
@Agent({
|
|
352
|
+
name: 'code_auditor',
|
|
353
|
+
description: 'Comprehensive code auditor that delegates to specialized sub-agents',
|
|
354
|
+
llm: { adapter: 'anthropic', model: 'claude-sonnet-4-20250514', apiKey: { env: 'ANTHROPIC_API_KEY' } },
|
|
355
|
+
inputSchema: {
|
|
356
|
+
repository: z.string().describe('Repository URL'),
|
|
357
|
+
branch: z.string().default('main').describe('Branch to audit'),
|
|
358
|
+
},
|
|
359
|
+
agents: [SecurityAuditorAgent, PerformanceAuditorAgent], // Sub-agents
|
|
360
|
+
tools: [CloneRepoTool, GenerateReportTool],
|
|
361
|
+
systemInstructions:
|
|
362
|
+
'Clone the repo, delegate security and performance audits to sub-agents, then compile a final report.',
|
|
363
|
+
})
|
|
364
|
+
class CodeAuditorAgent extends AgentContext {}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
## Swarm Configuration
|
|
368
|
+
|
|
369
|
+
Swarm mode enables multi-agent handoff, where agents can transfer control to each other during execution. Configure swarms using the `swarm` field.
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
@Agent({
|
|
373
|
+
name: 'triage_agent',
|
|
374
|
+
description: 'Triages incoming requests and hands off to specialists',
|
|
375
|
+
llm: { adapter: 'anthropic', model: 'claude-sonnet-4-20250514', apiKey: { env: 'ANTHROPIC_API_KEY' } },
|
|
376
|
+
inputSchema: {
|
|
377
|
+
request: z.string().describe('The incoming user request'),
|
|
378
|
+
},
|
|
379
|
+
swarm: {
|
|
380
|
+
role: 'coordinator',
|
|
381
|
+
handoff: [
|
|
382
|
+
{ agent: 'billing_agent', condition: 'Request is about billing or payments' },
|
|
383
|
+
{ agent: 'technical_agent', condition: 'Request is about technical issues' },
|
|
384
|
+
{ agent: 'general_agent', condition: 'Request does not match other categories' },
|
|
385
|
+
],
|
|
386
|
+
},
|
|
387
|
+
systemInstructions: 'Analyze the request and hand off to the appropriate specialist agent.',
|
|
388
|
+
})
|
|
389
|
+
class TriageAgent extends AgentContext {}
|
|
390
|
+
|
|
391
|
+
@Agent({
|
|
392
|
+
name: 'billing_agent',
|
|
393
|
+
description: 'Handles billing and payment inquiries',
|
|
394
|
+
llm: { adapter: 'anthropic', model: 'claude-sonnet-4-20250514', apiKey: { env: 'ANTHROPIC_API_KEY' } },
|
|
395
|
+
tools: [LookupInvoiceTool, ProcessRefundTool],
|
|
396
|
+
swarm: {
|
|
397
|
+
role: 'specialist',
|
|
398
|
+
handoff: [{ agent: 'triage_agent', condition: 'Request is outside billing scope' }],
|
|
399
|
+
},
|
|
400
|
+
})
|
|
401
|
+
class BillingAgent extends AgentContext {}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
## Function-Style Builder
|
|
405
|
+
|
|
406
|
+
For agents that do not need a class, use the `agent()` function builder.
|
|
407
|
+
|
|
408
|
+
```typescript
|
|
409
|
+
import { agent } from '@frontmcp/sdk';
|
|
410
|
+
import { z } from 'zod';
|
|
411
|
+
|
|
412
|
+
const QuickSummarizer = agent({
|
|
413
|
+
name: 'quick_summarizer',
|
|
414
|
+
description: 'Summarizes text quickly',
|
|
415
|
+
llm: {
|
|
416
|
+
adapter: 'anthropic',
|
|
417
|
+
model: 'claude-sonnet-4-20250514',
|
|
418
|
+
apiKey: { env: 'ANTHROPIC_API_KEY' },
|
|
419
|
+
},
|
|
420
|
+
inputSchema: {
|
|
421
|
+
text: z.string().describe('Text to summarize'),
|
|
422
|
+
maxLength: z.number().default(100).describe('Max summary length'),
|
|
423
|
+
},
|
|
424
|
+
})((input, ctx) => {
|
|
425
|
+
// Custom logic using ctx for completion calls
|
|
426
|
+
return ctx.completion({
|
|
427
|
+
messages: [{ role: 'user', content: `Summarize in ${input.maxLength} chars:\n${input.text}` }],
|
|
428
|
+
});
|
|
429
|
+
});
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
Register it the same way as a class agent: `agents: [QuickSummarizer]`.
|
|
433
|
+
|
|
434
|
+
## Remote and ESM Loading
|
|
435
|
+
|
|
436
|
+
Load agents from external modules or remote URLs without importing them directly.
|
|
437
|
+
|
|
438
|
+
**ESM loading** -- load an agent from an ES module:
|
|
439
|
+
|
|
440
|
+
```typescript
|
|
441
|
+
const ExternalAgent = Agent.esm('@my-org/agents@^1.0.0', 'ExternalAgent', {
|
|
442
|
+
description: 'An agent loaded from an ES module',
|
|
443
|
+
});
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
**Remote loading** -- load an agent from a remote URL:
|
|
447
|
+
|
|
448
|
+
```typescript
|
|
449
|
+
const CloudAgent = Agent.remote('https://example.com/agents/cloud-agent', 'CloudAgent', {
|
|
450
|
+
description: 'An agent loaded from a remote server',
|
|
451
|
+
});
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
Both return values that can be registered in `agents: [ExternalAgent, CloudAgent]`.
|
|
455
|
+
|
|
456
|
+
## Registration
|
|
457
|
+
|
|
458
|
+
Add agent classes (or function-style agents) to the `agents` array in `@FrontMcp` or `@App`.
|
|
459
|
+
|
|
460
|
+
```typescript
|
|
461
|
+
import { FrontMcp, App } from '@frontmcp/sdk';
|
|
462
|
+
|
|
463
|
+
@App({
|
|
464
|
+
name: 'review-app',
|
|
465
|
+
agents: [PRReviewerAgent, CodeAuditorAgent],
|
|
466
|
+
tools: [HelperTool],
|
|
467
|
+
})
|
|
468
|
+
class ReviewApp {}
|
|
469
|
+
|
|
470
|
+
@FrontMcp({
|
|
471
|
+
info: { name: 'my-server', version: '1.0.0' },
|
|
472
|
+
apps: [ReviewApp],
|
|
473
|
+
agents: [QuickSummarizer], // can also register agents directly on the server
|
|
474
|
+
})
|
|
475
|
+
class MyServer {}
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
## Nx Generator
|
|
479
|
+
|
|
480
|
+
Scaffold a new agent using the Nx generator:
|
|
481
|
+
|
|
482
|
+
```bash
|
|
483
|
+
nx generate @frontmcp/nx:agent
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
This creates the agent file, spec file, and updates barrel exports.
|
|
487
|
+
|
|
488
|
+
## Rate Limiting, Concurrency, and Timeout
|
|
489
|
+
|
|
490
|
+
Protect agents with throttling controls:
|
|
491
|
+
|
|
492
|
+
```typescript
|
|
493
|
+
@Agent({
|
|
494
|
+
name: 'expensive_agent',
|
|
495
|
+
description: 'An agent that performs expensive LLM operations',
|
|
496
|
+
llm: {
|
|
497
|
+
adapter: 'anthropic',
|
|
498
|
+
model: 'claude-sonnet-4-20250514',
|
|
499
|
+
apiKey: { env: 'ANTHROPIC_API_KEY' },
|
|
500
|
+
},
|
|
501
|
+
inputSchema: {
|
|
502
|
+
task: z.string(),
|
|
503
|
+
},
|
|
504
|
+
rateLimit: { maxRequests: 5, windowMs: 60_000 },
|
|
505
|
+
concurrency: { maxConcurrent: 1 },
|
|
506
|
+
timeout: { executeMs: 120_000 },
|
|
507
|
+
tags: ['expensive', 'llm'],
|
|
508
|
+
})
|
|
509
|
+
class ExpensiveAgent extends AgentContext {
|
|
510
|
+
async execute(input: { task: string }) {
|
|
511
|
+
// At most 5 calls per minute, 1 concurrent, 2 minute timeout
|
|
512
|
+
return super.execute(input);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
## Agent with Providers and Plugins
|
|
518
|
+
|
|
519
|
+
Agents can include their own providers and plugins for self-contained dependency management:
|
|
520
|
+
|
|
521
|
+
```typescript
|
|
522
|
+
@Agent({
|
|
523
|
+
name: 'database_agent',
|
|
524
|
+
description: 'Agent that interacts with databases',
|
|
525
|
+
llm: {
|
|
526
|
+
adapter: 'anthropic',
|
|
527
|
+
model: 'claude-sonnet-4-20250514',
|
|
528
|
+
apiKey: { env: 'ANTHROPIC_API_KEY' },
|
|
529
|
+
},
|
|
530
|
+
inputSchema: {
|
|
531
|
+
query: z.string().describe('Natural language database query'),
|
|
532
|
+
},
|
|
533
|
+
tools: [RunSqlTool, ListTablesTool, DescribeTableTool],
|
|
534
|
+
providers: [DatabaseProvider],
|
|
535
|
+
plugins: [RememberPlugin],
|
|
536
|
+
systemInstructions:
|
|
537
|
+
'You have access to a database. List tables, describe schemas, and run SQL to answer the user query.',
|
|
538
|
+
})
|
|
539
|
+
class DatabaseAgent extends AgentContext {}
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
## Agent with Resources and Prompts
|
|
543
|
+
|
|
544
|
+
Agents can include resources and prompts that are available within the agent's scope:
|
|
545
|
+
|
|
546
|
+
```typescript
|
|
547
|
+
@Agent({
|
|
548
|
+
name: 'docs_agent',
|
|
549
|
+
description: 'Agent that manages documentation',
|
|
550
|
+
llm: {
|
|
551
|
+
adapter: 'anthropic',
|
|
552
|
+
model: 'claude-sonnet-4-20250514',
|
|
553
|
+
apiKey: { env: 'ANTHROPIC_API_KEY' },
|
|
554
|
+
},
|
|
555
|
+
inputSchema: {
|
|
556
|
+
topic: z.string().describe('Topic to document'),
|
|
557
|
+
},
|
|
558
|
+
tools: [WriteFileTool, ReadFileTool],
|
|
559
|
+
resources: [DocsTemplateResource],
|
|
560
|
+
prompts: [TechnicalWritingPrompt],
|
|
561
|
+
})
|
|
562
|
+
class DocsAgent extends AgentContext {}
|
|
563
|
+
```
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Agent LLM Configuration Reference
|
|
2
|
+
|
|
3
|
+
## Supported Adapters
|
|
4
|
+
|
|
5
|
+
### Anthropic
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
llm: {
|
|
9
|
+
adapter: 'anthropic',
|
|
10
|
+
model: 'claude-sonnet-4-20250514',
|
|
11
|
+
apiKey: { env: 'ANTHROPIC_API_KEY' },
|
|
12
|
+
maxTokens: 4096,
|
|
13
|
+
}
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### OpenAI
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
llm: {
|
|
20
|
+
adapter: 'openai',
|
|
21
|
+
model: 'gpt-4o',
|
|
22
|
+
apiKey: { env: 'OPENAI_API_KEY' },
|
|
23
|
+
maxTokens: 4096,
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## API Key Sources
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
// From environment variable (recommended)
|
|
31
|
+
apiKey: {
|
|
32
|
+
env: 'ANTHROPIC_API_KEY';
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Direct string (not recommended for production)
|
|
36
|
+
apiKey: 'sk-...';
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Common Models
|
|
40
|
+
|
|
41
|
+
| Provider | Model | Use Case |
|
|
42
|
+
| --------- | -------------------------- | -------------------- |
|
|
43
|
+
| Anthropic | `claude-sonnet-4-20250514` | Fast, capable |
|
|
44
|
+
| Anthropic | `claude-opus-4-20250514` | Most capable |
|
|
45
|
+
| OpenAI | `gpt-4o` | General purpose |
|
|
46
|
+
| OpenAI | `gpt-4o-mini` | Fast, cost-effective |
|