Building ProtoScript services
Use ProtoScript services when a capability needs a behavior and state boundary, then project selected methods as tools for Buffaly to call.
This page is for service authors packaging web modules, JSON web service projections, static assets, and skills. It is not a guide for extending the host runtime itself.
Service boundary
A ProtoScript service owns the capability boundary: behavior, state, identity, lifecycle, and configuration. Tools are selected method projections through a flat tool interface. Treat the service as the durable surface and the tool calls as the callable views into it.
Service owns
- Capability identity and configuration.
- Runtime behavior and stateful dependencies.
- Method grouping and lifecycle expectations.
Tool exposes
- A flat callable operation Buffaly can select.
- Structured inputs and outputs for one method.
- A projection of service behavior, not a separate owner.
Web module lifecycle
For IBuffalyWebModule, Configure and MapRoutes run during host startup. They are runtime hooks, not install-time placement hooks.
Install-time placement belongs to the provisioning installer. New modules should not rely on InstallArtifacts; treat it as legacy for new module work.
Publish output
Publish the module normally and point the installer at the published folder. For example:
dotnet publish Buffaly.Agent.ImageGen.csproj -c Release -o C:\temp\imagegen
The publish folder should be self-describing. A healthy module publish has the compiled module, generated service projections, web assets, and any skill content the installer should place.
| Publish path | Purpose |
|---|---|
| *.dll, *.deps.json, *.runtimeconfig.json | Module assembly and runtime dependencies. |
| Generated/JsonWs | JSON web service manifests and stubs. |
| wwwroot | Static files served under the module web path. |
| Skills/<SkillName>/index.pts | Skill entry points, actions, prompts, and related files. |
Add explicit project content includes so Generated/JsonWs, wwwroot, and Skills copy into the publish output.
<ItemGroup>
<Content Include="Generated\JsonWs\**\*" CopyToPublishDirectory="PreserveNewest" />
<Content Include="wwwroot\**\*" CopyToPublishDirectory="PreserveNewest" />
<Content Include="Skills\**\*" CopyToPublishDirectory="PreserveNewest" />
</ItemGroup>
Installer discovery and verification
The installer should fail before copying files when the publish folder or host layout is ambiguous. Verification should be strict enough that the preview can show exactly what will be copied, registered, included, and receipted.
- Verify
installRootandpublishedOutputPath. - Find exactly one concrete
IBuffalyWebModuletype. - Validate a safe
ModuleName. - Resolve the host web root.
- Resolve the OpsAgent project root from
WorkerFeature.Feature.ProjectFilePath. - Verify JSON web service files, static files, and skill files.
- Require every skill folder to contain
index.pts. - Preview target paths, registration, includes, and receipt changes.
Installed layout mapping
Installers should map published content into owned locations. JSON web service files are copied directly to the host JSON web service folder. Static web files are isolated under the module name. New installs should not use wwwroot/modules.
| Source | Installed target |
|---|---|
| publish output | lib/web-modules/<ModuleName> |
| Generated/JsonWs | app/agent-web/wwwroot/JsonWs |
| wwwroot | app/agent-web/wwwroot/web-modules/<ModuleName> |
| Skills/<SkillName> | content/projects/OpsAgent/Skills/<SkillName> |
| skill include | content/projects/OpsAgent/Skills/index.pts |
| module registration | lib/web-modules/WebModules.json |
| install receipt | lib/web-modules/<ModuleName>/install-receipt.json |
lib folders. Installers and deployment scripts should fail or quarantine stale duplicate web-module DLLs outside the owned module folder.
Registration, skills, and receipt
WebModules.json is derived by the installer, not hand-authored. The installer should register the module with the discovered assembly path and concrete type name.
{
"Name": "ImageGen",
"AssemblyPath": "lib/web-modules/ImageGen/Buffaly.Agent.ImageGen.dll",
"TypeName": "Buffaly.Agent.ImageGen.ImageGenModule",
"Enabled": true,
"LoadOrder": 1000
}
Skills can be enabled by adding an idempotent include line to the OpsAgent skills index:
include "ImageGen/index.pts";
The install receipt records copied files and owned mutations for future uninstall or upgrade. Uninstall should remove owned registration, JSON web service files, the module static directory, installed skill folders and include lines, and lib/web-modules/<ModuleName>.
Validation checklist
- The service boundary is documented separately from the flat tool methods it projects.
- The module publishes DLL, dependency files, generated JSON web service files, static assets, and complete skill folders.
- The installer discovers one concrete web module type and previews every file copy and owned mutation.
- JSON web service files land in
wwwroot/JsonWs, and static files land underweb-modules/<ModuleName>. - Skills have
index.ptsand are enabled with idempotent include lines. - Registration is derived into
WebModules.json, and an install receipt records owned changes. - Deployment fails or quarantines stale duplicate web-module DLLs outside the owned module folder.