Buffaly services
Understand services as capability boundaries that can own lifecycle, identity, state, configuration, UI ownership, and multiple related methods.
Service mental model
A flat tool is the callable interface Buffaly invokes during a task. A service is the owner behind one or more callable methods. The service gives projected tools a stable source model and operating boundary.
Use services when the capability needs more than one isolated tool call: configured identity, lifecycle, shared state, initialization, authenticated clients, multiple methods, or an external system boundary.
Services, tools, and actions
| Need | Prefer | Why |
|---|---|---|
| Reuse a prompt-driven procedure | Prompt action or workflow memory | The work is mostly instruction, judgment, or sequencing. |
| Add one ontology-backed operation | ProtoScript action | Buffaly should discover and call one typed action. |
| Expose one stateless helper | Native tool | No identity, initialization, or related method family is needed. |
| Model a configured system or account | Service | Identity, state, configuration, initialization, or multiple methods matter. |
| Integrate an MCP server | MCP-backed service | Each binding can have different transport, auth, endpoint, command, tools, and boundary data. |
| Add host UI, routes, or JsonWs artifacts | Web module plus services/tools | Web modules own packaging and startup behavior; services own capability boundaries. |
Why services matter
Services matter when Buffaly needs to know which configured capability it is using. Examples include an MCP binding, a reporting connection, a workspace account, or a module-owned service surface.
ServiceName, Scope, Description, projected tool names, and configured binding identity.
Optional Initialize(), AutoInitialize, startup diagnostics, and per-session lifecycle state.
Endpoint, command, working directory, timeout, secret reference, route prefix, account, or tenant.
Multiple related To* methods can project as flat tools without losing service ownership.
Service lifecycle and diagnostics
During runtime initialization, Buffaly discovers concrete descendants of the Service root. A service can auto-initialize when AutoInitialize is enabled or not declared, but automatic initialization is intentionally constrained.
AutoInitializedefaults on when the service does not declare it;AutoInitialize=falseskips startup initialization.Initialize()must be parameterless to run automatically.- Startup diagnostics record completed, failed, skipped, or pending initialization.
- Initialization state is tracked by session key and service prototype name.
Default, optional, and runtime-available services
Do not treat every service-looking source file as an enabled runtime service. Availability has several levels.
- Service model present: a prototype descends from
Service, such asUserSecretsService,McpService,WikiService,BrowserWebModuleService, orComputerUseWebModuleService. - Project-included: the active ProtoScript project includes the file through
Project.pts,Core/index.pts, orSkills/index.pts. - Concrete service discovered: runtime diagnostics find a concrete descendant under the
Serviceroot. - Initialized or ready: diagnostics show initialization completed or no initializer is required.
- User-facing projected action: a selected service method follows the
To*projection convention or is exposed through a nestedTo*action prototype.
UserSecretsService and the generic McpService can be part of the included core project, while domain services such as Wiki, Browser, ComputerUse, JsonWs, Google Workspace, and search/session services may depend on enabled skill folders, credentials, routes, web modules, or remote endpoints.How to verify available services
Use this sequence when a user asks which services are available in a running Buffaly instance.
Start with Project.pts, Core/index.pts, and Skills/index.pts.
List services or inspect the hierarchy when the Services skill is loaded.
Use runtime diagnostics built from the service registrar to inspect projected names and initialization state.
Check secrets, MCP binding fields, JsonWs base URLs, web-module routes, generated artifacts, and provider settings.
If diagnostics disagree with implementation files, trust the running-session diagnostics for current availability and inspect source to understand why a service did not load or initialize.
Source model and projected tool names
The service method is the source model. The projected tool name is the flat callable interface that Buffaly can load and call.
| Service method | Projected tool name |
|---|---|
| McpService#FeedingFrenzy.ToListServerTools | McpService_FeedingFrenzy_ToListServerTools |
| McpService#GitHub.ToCallTool | McpService_GitHub_ToCallTool |
This preserves service identity and method ownership while still presenting a normal callable tool surface to the Buffaly agent.
Singleton versus per-binding services
Singleton-style
Appropriate only when there is genuinely one shared capability and instance identity does not change the meaning of a call.
Per-binding
Appropriate when each configured instance has its own boundary. MCP is the clearest example because different servers can have different endpoints, commands, transports, auth sources, capability sets, filesystem roots, and intended usage.
Concrete examples
MCP-backed CRM service: model the CRM server as a service instance that owns binding key, transport, endpoint or command, token secret reference, timeout, and description. Buffaly can list remote tools or call a remote tool without losing configured service identity.
UserSecretsService: treat this as a core boundary for sensitive credentials, but remember that secret values are user/environment specific and should not be copied into ontology memory or documentation.
Web modules: modules can own web-facing packaging and startup behavior. Installed web modules live under lib/web-modules, static assets are exposed under wwwroot/web-modules/<ModuleName>, and generated JsonWs manifests/stubs are copied to wwwroot/JsonWs so the JsonWs loader can discover them.