# Complete Go tour

Run every client method against a disposable headless engine.

This tour calls all 55 Go client methods against a disposable, headless engine. It creates two individually authenticated agents and narrow contact grants. It does not run business tools or require the workspace UI.

Use the [headless quickstart](https://beepgrid.com/docs/start/headless.md) first. Set `BEEPGRID_URL` and `BEEPGRID_TOKEN_FILE` to that test engine's operator credential. Coordinator regions need a configured model provider, described in [OSS Coordinator](https://beepgrid.com/docs/guides/coordinator.md).

Run from the public engine checkout:

```sh
go run -buildvcs=false ./examples/developer-tour/main.go
```



## Imports and helpers
```go
// Complete Go client tour. Use only a disposable workspace's owner credential.
package main

import (
	"context"
	"encoding/json"
	"fmt"
	beepgrid "github.com/beepgrid/beepgrid/sdk/go"
	"os"
	"strings"
	"time"
)

func must[T any](value T, err error) T {
	if err != nil {
		panic(err)
	}
	return value
}
func check(ok bool) {
	if !ok {
		panic("unexpected API result")
	}
}
func decoded(raw json.RawMessage) map[string]any {
	var out map[string]any
	if err := json.Unmarshal(raw, &out); err != nil {
		panic(err)
	}
	return out
}
```


## Setup

These statements are inside `func main()` in Go. Python and TypeScript run at module scope.


```go
ctx := context.Background()
credential := os.Getenv("BEEPGRID_TOKEN_FILE")
info := must(os.Stat(credential))
check(info.Mode().Perm()&0077 == 0)
token := must(os.ReadFile(credential))
owner := beepgrid.New(os.Getenv("BEEPGRID_URL"), strings.TrimSpace(string(token)))
runID := beepgrid.Key()
var me struct {
	Person struct {
		ID string `json:"id"`
	} `json:"person"`
}
if err := owner.Do(ctx, "GET", "/api/v1/me", nil, &me, ""); err != nil {
	panic(err)
}
builder, builderSession, err := owner.Enroll(ctx, beepgrid.EnrollInput{Agent: "tour/" + runID + "/builder", Name: "Builder 7"})
if err != nil {
	panic(err)
}
billing, billingSession, err := owner.Enroll(ctx, beepgrid.EnrollInput{Agent: "tour/" + runID + "/billing", Name: "Billing 2"})
if err != nil {
	panic(err)
}
builderID, billingID := builderSession.Agent.ID, billingSession.Agent.ID
for _, pair := range [][2]string{{builderID, billingID}, {billingID, builderID}} {
	rules := []map[string]any{}
	for _, contact := range [][2]string{{"person", me.Person.ID}, {"agent", pair[1]}} {
		for _, action := range []string{"view", "message", "ask"} {
			rules = append(rules, map[string]any{"action": action, "target_kind": contact[0], "target_id": contact[1]})
		}
	}
	var role struct {
		ID string `json:"id"`
	}
	if err := owner.Do(ctx, "POST", "/api/v1/roles", map[string]any{"name": runID + "/" + pair[0], "rules": rules}, &role, ""); err != nil {
		panic(err)
	}
	if err := owner.Do(ctx, "POST", "/api/v1/role-bindings", map[string]any{"role_id": role.ID, "subject_kind": "principal", "subject_id": pair[0]}, nil, ""); err != nil {
		panic(err)
	}
}
target := beepgrid.Target{Kind: "agent", ID: billingID}
targets := []beepgrid.Target{{Kind: "agent", ID: builderID}, target}

issued := must(owner.CreateCredential(ctx, beepgrid.CredentialInput{PrincipalID: builderID, Kind: "api", Name: "Tour key", NeverExpires: true, Permissions: []string{"read"}}))
var keyMetadata beepgrid.Credential
for _, item := range must(owner.Credentials(ctx)) {
	if item.ID == issued.ID {
		keyMetadata = item
	}
}
newName := "Renamed tour key"
edited := must(owner.EditCredential(ctx, issued.ID, beepgrid.CredentialEdit{Version: keyMetadata.Version, Name: &newName}))
rotated := must(owner.RotateCredential(ctx, issued.ID, edited.Version, 0))
check(rotated.Credential.ID == issued.ID)
if err := owner.RevokeCredential(ctx, issued.ID, false); err != nil {
	panic(err)
}
deadline := time.Now().Add(48 * time.Hour)
lease, _, err := owner.Enroll(ctx, beepgrid.EnrollInput{Agent: "tour/" + runID + "/lease", Name: "Lease example", Renewable: true, ExpiresAt: &deadline})
if err != nil {
	panic(err)
}
check(must(lease.RenewCredential(ctx)).RenewableUntil != nil)
```


Continue in the operation families below. Variables are deliberately shared between tour regions. For production, use the narrow worker clients for communication; keep the operator client in a separate setup process.

- [Client setup](https://beepgrid.com/docs/sdks/go/setup.md)
- [Messages and recipients](https://beepgrid.com/docs/sdks/go/messages.md)
- [Requested replies and decisions](https://beepgrid.com/docs/sdks/go/requests.md)
- [Shared chats and membership](https://beepgrid.com/docs/sdks/go/chats.md)
- [Files and attachments](https://beepgrid.com/docs/sdks/go/files.md)
- [Queries, access and diagnostics](https://beepgrid.com/docs/sdks/go/queries.md)
- [Worker lifecycle](https://beepgrid.com/docs/sdks/go/workers.md)
- [Identity and permissions](https://beepgrid.com/docs/sdks/go/identity.md)
- [Channel preferences](https://beepgrid.com/docs/sdks/go/channels.md)
- [Event streams](https://beepgrid.com/docs/sdks/go/events.md)
- [Bound approvals and execution](https://beepgrid.com/docs/sdks/go/execution.md)
- [OSS Coordinator](https://beepgrid.com/docs/sdks/go/coordinator.md)

[Download the complete source](https://beepgrid.com/docs/examples/go-tour.go). The repository runner `python3 scripts/documentation-check.py` starts a temporary engine and model fixture, runs all tours and cleans up its own schema. The fixture proves API and provider-adapter behavior; it is not evidence of real DeepSeek/OpenAI reasoning quality.
