Skip to Content
DevelopDefining Agents and Components

Defining Golem Components

Creating a project

Golem’s command line interface provides a set of predefined, Golem-specific templates to choose from as a starting point.

To get started from scratch, first create a new application using the TypeScript template:

golem new --template ts --yes my-app cd my-app

An application can consist of multiple components. Add a new component by choosing from one of the available templates. To see the list of available templates, run:

golem templates

Then create a new component using the chosen template:

golem new . --template ts --component-name my:component --yes

TypeScript agents, tools, and middleware

TypeScript components use one default guest world for agents, tools, snapshots, and tool middleware. Select the ts component template regardless of which of these categories the component exports:

golem.yaml
components: my:middleware: dir: middleware templates: ts

Standalone middleware components remain supported. Import their authoring APIs from the middleware entry point; unused agent and tool discovery returns empty lists:

import { toolDefinition, universalToolMiddleware, } from '@golemcloud/golem-ts-sdk/middleware';

The default guest imports golem:tool/host; ambient calls remain subject to runtime permission checks. Invocation-scoped underlying access still advances the pinned middleware chain.

Defining agents

Defining Golem agents is done using the Golem SDK, which is included in all the templates provided by golem.

An agent is declared with defineAgent(...) and given its behaviour with .implement(...):

import { z } from 'zod'; import { defineAgent, method } from '@golemcloud/golem-ts-sdk'; export const MyAgent = defineAgent({ name: 'MyAgent', id: { /* constructor parameters — see below */ }, methods: { // ... }, }); export const MyAgentImpl = MyAgent.implement({ init: () => ({ /* initial state */ }), methods: { // ... }, });

An agent component must define at least one agent, but can also define multiple ones.

Agent constructors

Every agent must define a constructor with an arbitrary number of parameters. These parameters form the agent identifier. Every possible parameter value combination identifies a particular agent instance.

For example, an agent working on a particular user’s particular request could be defined as:

import { z } from 'zod'; import { defineAgent } from '@golemcloud/golem-ts-sdk'; export const RequestHandler = defineAgent({ name: 'RequestHandler', id: { userId: z.string(), requestId: z.string() }, methods: { // ... }, });

The Effect agent shown here is identified by RequestHandler("user-123", "request-456"); agent identifiers preserve the declared agent name.

Agent methods

Every method an agent declares is an agent method, which can be called by other remote agents, externally through Golem’s invocation API, and can also be mapped to HTTP APIs.

Agent methods can (and should) be also annotated with the metadata such as prompt and description

  • prompt should provide information for an external AI to understand what needs to be passed to the method as parameters
  • description should be a human-readable description of what the method does

This metadata is stored in the Golem component and can be used when exposing the agents through MCP, for example.

The following example shows the use of how to attach these metadata to simple agent methods in different languages

import { z } from 'zod'; import { defineAgent, method } from '@golemcloud/golem-ts-sdk'; const TaskDetails = z.object({ description: z.string(), priority: z.number() }); const RequestHandlerStatus = z.object({ status: z.enum(['success', 'failure']), summary: z.string(), }); export const RequestHandler = defineAgent({ name: 'RequestHandler', id: { userId: z.string(), requestId: z.string() }, methods: { addDetails: method({ input: { details: TaskDetails }, returns: RequestHandlerStatus, description: "Adds some more details to the request handler about the task being performed. The result is an update of the current status.", promptHint: "Enter new details about the task", }), }, });

Agent methods can be both sync or async. Effect TypeScript handlers always return an Effect, whether the work represented by that Effect is synchronous or asynchronous.

Supported data types

The SDK supports a large variety of data types in agent constructors and agent methods, both in parameter and return type position. Validation timing is SDK-specific; Effect TypeScript validates whether its schemas have an unambiguous Golem representation during registration and discovery.

In TypeScript, declare constructor parameters, method inputs, and return values using supported runtime schemas, such as Zod schemas. Use z.object(...) for records and z.enum(...) for string alternatives; TypeScript types are inferred from these schemas.

Library support

See the JS APIs page for a detailed overview of all the supported Web Platform and Node.js APIs. Most 3rd party libraries can be installed using npm and used in the agent code, as long as they only rely on the supported APIs and do not require native addons.

Agent mode - durable or ephemeral

By default every agent is durable. To define an ephemeral agent, override the agent mode in the agent definition:

export const EphemeralAgent = defineAgent({ name: 'EphemeralAgent', mode: 'ephemeral', id: { name: z.string() }, methods: { // ... }, });

Agent configuration

It is often required to pass configuration values to agents when they are started.

Golem supports two ways of doing this:

  1. Defining key-value pairs available as environment variables.
  2. Defining dedicated typed configuration values.

Environment variables

Environment variables are accessible through the node:process module:

import { env } from "node:process";

Environment variables can be specified when an agent is explicitly created, but there are some environment variables that are always set by Golem:

  • GOLEM_AGENT_ID - the ID of the agent
  • GOLEM_AGENT_TYPE - the agent type (first part of the agent ID)
  • GOLEM_COMPONENT_ID - the ID of the agent’s component
  • GOLEM_COMPONENT_REVISION - the revision of the component used for this agent

In addition to these, when using Agent to Agent communication, agents created by remote calls inherit the environment variables of the caller.

This feature makes environment variables a good fit for passing configuration such as hostnames, ports, or access tokens to trees of agents.

Default environment variables

It is possible to define default environment values and config key-value pairs for a component using the app manifest. These values are automatically set for each agent created from the component, but can be overridden when creating the agent.

To set component level environment variables, use the env section of the golem.yaml:

components: my:component: env: MY_ENV_VAR: "some value" ANOTHER_ENV_VAR: "another value"

Per-agent configuration

Configuration resolves from the component template and component first. Agent templates are then applied, followed by agent properties, environment presets, and finally custom presets. Each level can define env (environment variables) and files (initial filesystem), with later, more specific levels overriding earlier ones according to their merge modes.

Agent-level configuration in golem.yaml

agents: InboxAgent: env: OPENAI_API_KEY: "{{ OPENAI_API_KEY }}" MODEL: gpt-4.1-mini files: - sourcePath: ./prompts/inbox-system.md targetPath: /prompts/system.md permissions: read-only config: defaultQueue: general summarizeReplies: true EscalationAgent: env: JIRA_BASE_URL: https://acme.atlassian.net files: - sourcePath: ./prompts/escalation-system.md targetPath: /prompts/system.md permissions: read-only

Merge modes

By default, child-level environment variables are upserted (added or updated) into parent values. This can be changed with envMergeMode:

ModeBehavior
upsert(default) Add new keys, overwrite existing ones
replaceDiscard all parent env vars, use only this level’s values
removeRemove the listed keys from the parent map

Similarly, filesMergeMode controls how initial files are merged: append (default), prepend, or replace.

Presets

Both components and agents support presets that can override configuration per deployment target:

environments: local: default: true server: local componentPresets: local prod: server: cloud componentPresets: cloud