Downcity
Services

Service Lifecycle

Understand start, stop, and command, plus when the SDK actually auto-starts services

Service Lifecycle

The main service lifecycle hooks are:

  • start
  • stop
  • command

They live under lifecycle.

Minimal example

readonly lifecycle = {
  start: async (context) => {
    // start worker, connection, watcher
  },
  stop: async () => {
    // release resources
  },
  command: async ({ context, command, payload }) => {
    return {
      success: true,
      message: "ok",
    };
  },
};

start

Good for:

  • starting workers
  • opening connections
  • preparing long-lived caches
  • starting channel listeners

stop

Good for:

  • stopping workers
  • closing connections
  • clearing timers
  • releasing in-memory resources

command

This is closer to a service-level control hook.

Examples:

  • reload
  • reschedule
  • flush

These are not always regular business actions, but they still belong to the service itself.

When the current SDK auto-starts services

This is the most important practical rule.

In the current SDK, the stable automatic service startup points are mainly:

  • agent.start({ http: { ... } })
  • agent.start({ rpc: true })

That is because those paths call ensureServicesStarted() before exposing endpoints.

What you should not assume today

Do not assume that:

  • new Agent(...) automatically runs start
  • agent.session() automatically runs start
  • session.prompt() automatically completes the full background lifecycle of every service

The current code does not make that broader guarantee.

Current SDK boundary around stop

The SDK currently does not expose a public:

  • agent.stopServices()

So you should not design critical cleanup around the assumption that the SDK will always perform a global automatic stop for you.

The safer pattern is:

  • make start idempotent
  • make stop idempotent
  • keep resource management resilient to repeated calls

Design advice for custom services

1. Prefer lightweight services when you do not need background runtime

If the service mainly provides actions and state, it can stay simple.

2. If you do need background runtime, treat HTTP or RPC startup as the service startup boundary

That is the clearest current model.

3. Do not push critical state into module-level singletons

That breaks the per-agent boundary the SDK is trying to preserve.