go/docs/getting-started.md
Snider 1f0c618b7a fix: rewrite 4 stale docs — messaging, primitives, index, getting-started, testing
All PERFORM/RegisterTask/type Task any references replaced with
named Action patterns. Every code example now uses the v0.8.0 API.

- docs/messaging.md: full rewrite — ACTION/QUERY + named Actions + Task
- docs/primitives.md: full rewrite — added Action, Task, Registry, Entitlement
- docs/index.md: full rewrite — updated surface table, quick example, doc links
- docs/getting-started.md: 2 RegisterTask+PERFORM blocks → Action pattern
- docs/testing.md: 1 RegisterTask+PERFORM block → Action pattern

An agent reading any doc file now gets compilable code.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 17:13:27 +00:00

4.4 KiB

title description
Getting Started Build a first CoreGO application with the current API.

Getting Started

This page shows the shortest path to a useful CoreGO application using the API that exists in this repository today.

Install

go get dappco.re/go/core

Create a Core

New takes zero or more core.Options slices, but the current implementation only reads the first one. In practice, treat the constructor as core.New(core.Options{...}).

package main

import "dappco.re/go/core"

func main() {
	c := core.New(core.Options{
		{Key: "name", Value: "agent-workbench"},
	})

	_ = c
}

The name option is copied into c.App().Name.

Register a Service

Services are registered explicitly with a name and a core.Service DTO.

c.Service("audit", core.Service{
	OnStart: func() core.Result {
		core.Info("audit service started", "app", c.App().Name)
		return core.Result{OK: true}
	},
	OnStop: func() core.Result {
		core.Info("audit service stopped", "app", c.App().Name)
		return core.Result{OK: true}
	},
})

This registry stores core.Service values. It is a lifecycle registry, not a typed object container.

Register a Query, Task, and Command

type workspaceCountQuery struct{}

type createWorkspaceTask struct {
	Name string
}

c.RegisterQuery(func(_ *core.Core, q core.Query) core.Result {
	switch q.(type) {
	case workspaceCountQuery:
		return core.Result{Value: 1, OK: true}
	}
	return core.Result{}
})

c.Action("workspace.create", func(_ context.Context, opts core.Options) core.Result {
	name := opts.String("name")
	path := "/tmp/agent-workbench/" + name
	return core.Result{Value: path, OK: true}
})

c.Command("workspace/create", core.Command{
	Action: func(opts core.Options) core.Result {
		return c.Action("workspace.create").Run(context.Background(), opts)
	},
})

Start the Runtime

if !c.ServiceStartup(context.Background(), nil).OK {
	panic("startup failed")
}

ServiceStartup returns core.Result, not error.

Run Through the CLI Surface

r := c.Cli().Run("workspace", "create", "--name=alpha")
if r.OK {
	fmt.Println("created:", r.Value)
}

For flags with values, the CLI stores the value as a string. --name=alpha becomes opts.String("name") == "alpha".

Query the System

count := c.QUERY(workspaceCountQuery{})
if count.OK {
	fmt.Println("workspace count:", count.Value)
}

Shut Down Cleanly

_ = c.ServiceShutdown(context.Background())

Shutdown cancels c.Context(), broadcasts ActionServiceShutdown{}, waits for background tasks to finish, and then runs service stop hooks.

Full Example

package main

import (
	"context"
	"fmt"

	"dappco.re/go/core"
)

type workspaceCountQuery struct{}

type createWorkspaceTask struct {
	Name string
}

func main() {
	c := core.New(core.Options{
		{Key: "name", Value: "agent-workbench"},
	})

	c.Config().Set("workspace.root", "/tmp/agent-workbench")
	c.Config().Enable("workspace.templates")

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

	c.RegisterQuery(func(_ *core.Core, q core.Query) core.Result {
		switch q.(type) {
		case workspaceCountQuery:
			return core.Result{Value: 1, OK: true}
		}
		return core.Result{}
	})

	c.Action("workspace.create", func(_ context.Context, opts core.Options) core.Result {
		name := opts.String("name")
		path := c.Config().String("workspace.root") + "/" + name
		return core.Result{Value: path, OK: true}
	})

	c.Command("workspace/create", core.Command{
		Action: func(opts core.Options) core.Result {
			return c.Action("workspace.create").Run(context.Background(), opts)
		},
	})

	if !c.ServiceStartup(context.Background(), nil).OK {
		panic("startup failed")
	}

	created := c.Cli().Run("workspace", "create", "--name=alpha")
	fmt.Println("created:", created.Value)

	count := c.QUERY(workspaceCountQuery{})
	fmt.Println("workspace count:", count.Value)

	_ = c.ServiceShutdown(context.Background())
}

Next Steps

  • Read primitives.md next so the repeated shapes are clear.
  • Read commands.md if you are building a CLI-first system.
  • Read messaging.md if services need to collaborate without direct imports.