Buffaly Logo
Reference

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 installRoot and publishedOutputPath.
  • Find exactly one concrete IBuffalyWebModule type.
  • 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
Duplicate DLL warning: web-module DLLs must not be duplicated into project 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 under web-modules/<ModuleName>.
  • Skills have index.pts and 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.

Next