agent/.core/reference/docs/services.md
Virgil de7844dcb9 fix(ax): restore live agent reference paths
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-29 20:24:58 +00:00

3.2 KiB

title description
Services Register, inspect, and lock CoreGO services.

Services

In CoreGO, a service is a named lifecycle entry stored in the Core registry.

Register a Service

c := core.New()

r := c.Service("audit", core.Service{
	OnStart: func() core.Result {
		core.Info("audit started")
		return core.Result{OK: true}
	},
	OnStop: func() core.Result {
		core.Info("audit stopped")
		return core.Result{OK: true}
	},
})

Registration succeeds when:

  • the name is not empty
  • the registry is not locked
  • the name is not already in use

Read a Service Back

r := c.Service("audit")
if r.OK {
	svc := r.Value.(*core.Service)
	_ = svc
}

The returned value is *core.Service.

List Registered Services

names := c.Services()

Important Detail

The current registry is map-backed. Services(), Startables(), and Stoppables() do not promise a stable order.

Lifecycle Snapshots

Use these helpers when you want the current set of startable or stoppable services:

startables := c.Startables()
stoppables := c.Stoppables()

They return []*core.Service inside Result.Value.

Lock the Registry

CoreGO has a service-lock mechanism, but it is explicit.

c := core.New()

c.LockEnable()
c.Service("audit", core.Service{})
c.Service("cache", core.Service{})
c.LockApply()

After LockApply, new registrations fail:

r := c.Service("late", core.Service{})
fmt.Println(r.OK) // false

The default lock name is "srv". You can pass a different name if you need a custom lock namespace.

For the service registry itself, use the default "srv" lock path. That is the path used by Core.Service(...).

NewWithFactories

For GUI runtimes or factory-driven setup, CoreGO provides NewWithFactories.

r := core.NewWithFactories(nil, map[string]core.ServiceFactory{
	"audit": func() core.Result {
		return core.Result{Value: core.Service{
			OnStart: func() core.Result {
				return core.Result{OK: true}
			},
		}, OK: true}
	},
	"cache": func() core.Result {
		return core.Result{Value: core.Service{}, OK: true}
	},
})

Important Details

  • each factory must return a core.Service in Result.Value
  • factories are executed in sorted key order
  • nil factories are skipped
  • the return value is *core.Runtime

Runtime

Runtime is a small wrapper used for external runtimes such as GUI bindings.

r := core.NewRuntime(nil)
rt := r.Value.(*core.Runtime)

_ = rt.ServiceStartup(context.Background(), nil)
_ = rt.ServiceShutdown(context.Background())

Runtime.ServiceName() returns "Core".

ServiceRuntime[T] for Package Authors

If you are writing a package on top of CoreGO, use ServiceRuntime[T] to keep a typed options struct and the parent Core together.

type repositoryServiceOptions struct {
	BaseDirectory string
}

type repositoryService struct {
	*core.ServiceRuntime[repositoryServiceOptions]
}

func newRepositoryService(c *core.Core) *repositoryService {
	return &repositoryService{
		ServiceRuntime: core.NewServiceRuntime(c, repositoryServiceOptions{
			BaseDirectory: "/srv/repos",
		}),
	}
}

This is a package-authoring helper. It does not replace the core.Service registry entry.