Skip to main content
Agents are autonomous AI units that have their own LLM provider, can execute tools, and are themselves callable as tools. They enable sophisticated multi-agent architectures where specialized agents can be composed and orchestrated.
Agents build on the MCP Tools specification—each agent is automatically exposed as an invoke_<agent-id> tool that any MCP client can call. Everything the agent declares that gates a tool (availableWhen, rateLimit, concurrency, timeout, authorities, and plugin fields such as approval or featureFlag) applies to that tool.
Nx users: Scaffold with nx g @frontmcp/nx:agent my-agent --project my-app. See Agent Generator.

Why Agents?

In the Model Context Protocol, agents serve a distinct purpose from tools, resources, and prompts: Agents are ideal for:
  • Complex reasoning — tasks requiring multiple LLM calls and tool use
  • Specialized expertise — domain-specific agents (research, writing, coding)
  • Orchestration — coordinating multiple sub-agents for complex workflows
  • Isolation — agents with their own tools, resources, and providers

Creating Agents

Class Style (Default Behavior)

The simplest agent requires no execute() method. The default behavior automatically:
  • Runs the execution loop with the LLM
  • Connects tools and executes them as needed
  • Sends notifications on tool calls and output

Class Style (Custom Behavior)

Override execute() only when you need custom pre/post processing:

Function Style

For simpler agents, use the functional builder:

Invocation, Hooks and Request Context

Calling invoke_<agent-id> runs two flows:
  1. tools:call-tool for the agent’s tool, which applies everything the agent declares: authorities, rateLimit, concurrency, timeout, and plugin fields such as approval or featureFlag.
  2. agents:call-agent, which runs the agent. Hooks registered for agent invocation run here: AgentCallHook in a plugin, or @AgentCallHook.Will(...) / .Did(...) methods on the agent class itself.
Inside the agent, including a custom execute(), this.context (request id, session, auth info) and CONTEXT-scoped providers are available, as in a tool.

Registering Agents

Add agents to your app via the agents array:
Each agent is automatically exposed as a tool:
  • invoke_research-agent
  • invoke_calculator-agent
  • invoke_writer-agent

Loading from npm or Remote Servers

Mix local agents with those loaded from npm or proxied from remote servers:
Agent.esm() and Agent.remote() load individual agents. For loading entire apps, use App.esm() or App.remote().

Environment Availability

Restrict when an agent is discoverable and invocable using availableWhen:
See Environment Awareness for the full reference.

LLM Configuration

Agents require an LLM configuration. FrontMCP provides native adapters for OpenAI and Anthropic SDKs with built-in retry logic, streaming support, and token tracking.

Built-in Providers (Shorthand)

The simplest way to configure an LLM — the SDK auto-creates the appropriate adapter:

OpenAI Adapter (Direct)

For full control, use OpenAIAdapter directly. Supports the Chat Completions API (default) and the Responses API:

OpenAI-Compatible Providers

Use baseUrl to connect to any OpenAI-compatible API (OpenRouter, Azure, Groq, Mistral, etc.):

Anthropic Adapter (Direct)

Custom Adapter

Implement AgentLlmAdapter for any other provider:

Agent-Scoped Components

Agents can have their own isolated tools, resources, prompts, and providers:

Swarm Configuration

Control agent visibility for multi-agent coordination:

Visibility Patterns

Orchestrator Pattern — A central agent coordinates specialized workers:

Execution Configuration

Control agent execution behavior:

Tool Execution Mode

By default, agents execute tools through the full call-tool flow, which includes:
  • Plugin hooks (caching, rate limiting, audit logging)
  • Authorization checks
  • Tool middleware and transformations
The plugin hooks are those of the plugins installed on the agent (@Agent({ plugins })), which apply to the agent’s own tools the way an app’s plugins apply to the app’s tools. Plugins on the server or the app don’t reach them. Up to 1.8.2, a plugin on an agent with a hook of its own (such as FeatureFlagPlugin) made every tool call of that agent fail with Unsupported hook owner kind: "agent". For performance-critical scenarios, you can disable flow execution:
Setting useToolFlow: false bypasses all plugin hooks and middleware. Only use this when you need maximum performance and don’t require plugin features.

Overriding Behavior

Customize agent behavior by overriding methods in AgentContext:

Progress Notifications

Keep users informed during long operations using manual or automatic notifications.

Manual Notifications

Use this.notify() to send custom messages at specific points:
Use this.progress() for progress bars when the client provides a progressToken:

Automatic Progress (Opt-in)

Enable enableAutoProgress to automatically send progress notifications during the agent execution loop:
When enabled, the agent automatically sends progress updates at these lifecycle points:
Auto progress requires both enableAutoProgress: true and enableNotifications: true (the default). Progress notifications are only sent if the client includes a progressToken in the request’s _meta field.

Error Handling

Handle errors gracefully in agents:

Output that does not match outputSchema

An agent’s reply is checked against its outputSchema exactly as a tool’s result is. When it does not match, for example the model answers {"priority":"urgent"} for a z.enum(['low', 'normal', 'high']) field or replies with text that is not JSON, the call fails with _meta.code: "INVALID_OUTPUT" and the message Tool output validation failed (output does not match outputSchema at priority). The result carries no stack trace or server file path.

Nested Agents

Agents can contain other agents, creating hierarchical structures: