MODULE 03 · LESSON 3.2
Build a plugin that participates in the agent lifecycle
Build a plugin that shares the owning agent's context and lifecycle.
Lesson 12 of 86 · FabrCore 2.0
Overview
IFabrCorePlugin.InitializeAsync receives AgentConfiguration and trusted services. This lets the plugin use a principal-bound connection, state or agent host without asking the model to supply infrastructure credentials. Its public described methods become callable tools.
Initialization binds trusted dependencies
InitializeAsync receives the owning agent's configuration and trusted services. Resolve the request-system client or connection there, instead of letting the model supply a base URL, principal or credential on every call. Per-agent initialization gives the plugin a defined owner and a point to validate its settings before requests arrive.
Registration and attachment are both required
The Host must discover the plugin implementation, and the instance's Plugins list must select its alias. Args entries using the documented plugin-alias:setting convention are configuration inputs, not automatic tool registration. The sample RequestPlugin uses fixture data; an HTTP-backed implementation can later keep the same narrow lookup interface while replacing its internal dependency.
Initialize and attach the request plugin
Download the Operations Desk source. The README lists project setup, package prerequisites and local ports.
- Add RequestPlugin.cs below to the agents assembly, then rebuild and restart the Host so discovery sees requests. The fixture has no external dependencies and performs no writes.
- Use the request below to create tool-assistant with the requests plugin. For an existing instance, use an explicit configuration update; ordinary ensure creation may retain its old plugin list.
- Send a message to tool-assistant asking it to look up SR-1042. Inspect the actual tool result, whose fixture status is Open.
using System.ComponentModel;
using FabrCore.Core;
using FabrCore.Sdk;
[PluginAlias("requests")]
[Description("Read fixture service requests. Does not update external systems.")]
public sealed class RequestPlugin : IFabrCorePlugin
{
public Task InitializeAsync(AgentConfiguration config, IServiceProvider services)
=> Task.CompletedTask;
[Description("Look up a service request by its exact ID. Returns null if absent.")]
public Task<RequestRecord?> GetRequest(
[Description("Request ID, for example SR-1042")] string requestId)
=> Task.FromResult(requestId == "SR-1042"
? new RequestRecord(requestId, "Printer unavailable", "Open") : null);
}
public sealed record RequestRecord(string Id, string Summary, string Status);
POST /fabrcoreapi/agent/create
x-user-handle: dev
Content-Type: application/json
[
{
"handle": "tool-assistant",
"agentType": "ops-assistant",
"models": "default",
"plugins": ["requests"]
}
]
A Cloud Server can select plugins on an existing instance through the same Host administration contract. It cannot compile RequestPlugin.cs or install an undiscovered alias. Deploy the class first.
The example targets the disposable ai-assistant from module 1. Read its full configuration and preserve fields you are not changing; the illustrated body is the small tutorial configuration. The revision is the value returned by that read.
- Discover installed plugins using the agent catalog endpoint. Read ai-assistant/configuration and retain its revision.
- Add requests to the current configuration and submit the configure action against that revision. Reload/review on 412; investigate a busy 409 rather than forcing an unrelated reset.
- Read the configuration back and perform the same fixture lookup. A saved blueprint alone is not confirmation that the active instance now has the plugin.
GET /fabrcoreapi/admin/v1/principals/dev/agents/catalog
Authorization: Bearer <administration-credential>
GET /fabrcoreapi/admin/v1/principals/dev/agents/ai-assistant/configuration
Authorization: Bearer <administration-credential>
POST /fabrcoreapi/admin/v1/principals/dev/agents/ai-assistant/actions/configure
Authorization: Bearer <administration-credential>
Content-Type: application/json
{
"revision": "<revision-from-read>",
"configuration": {
"handle": "ai-assistant",
"agentType": "ops-assistant",
"models": "default",
"plugins": ["requests"]
}
}
Verify the selected plugin and returned fixture
- Deploy the plugin class, then inspect discovery for the requests alias. If the alias is absent, selecting it in an instance will not manufacture the implementation.
- Create or explicitly reconfigure a disposable AI instance with Plugins containing requests. Ask “Look up SR-1042 and report its status.” Inspect a real tool call and compare the result with the fixture in RequestPlugin.cs.
- Remove requests from that instance using an explicit update/reconfiguration and repeat. The agent should no longer have that lookup tool; a natural-language claim alone is not evidence of plugin attachment.
You have verified both discovery and per-instance attachment. Updating a JSON file without updating the existing instance is a common reason a plugin appears to be ignored.
If the result is different
Avoid singleton mutable per-agent state and duplicate tool registration. For external authentication, use connection credential references instead of secrets in Args.
Go deeper
Explore the related documentation.