Forking Agents
Explanation
Golem agents are single threaded. To achieve parallel execution, it is possible to spawn child agents and communicate with them using RPC, as described on the Agent to Agent communication page.
A simpler way is to use the fork API. The fork API consists of a single host function, defined as the following:
declare module 'golem:api/host@1.1.7' {
// ...
/**
* Indicates which worker the code is running on after `fork`
*/
export type ForkResult = "original" | "forked";
/**
* Forks the current worker at the current execution point. The new worker gets the `new-name` worker name,
* and this worker continues running as well. The return value is going to be different in this worker and
* the forked worker.
*/
export function fork(newName: string): ForkResult;
}
When called, a new agent is created using the given name, with exactly the same state as the one that called the fork
function. The execution continues in both the original and the new agents, with a different fork-result
result value in each.
This is a low-level API that requires passing the new agent ID as a string. This ID has to be a valid agent-id, consisting of the agent type (same as the agent type of the current agent) and valid constructor parameters. However, the constructor parameters must contain an element distinguishing the new agent from the original one.
One simple way to do that is to use an extra parameter to the agent constructor that is not used by the agent itself, but is used to distinguish the new agent from the original one; it needs to have a clear default value (like 0, or empty string, etc.) to be able to find the root agent.
Future Golem versions will provide a more user-friendly, higher level API to implement this functionality.
Usage
Using this fork
function from a component that was created from Golem's built-in templates is straightforward because access to the Golem specific host functions is already set up.
The following code snippet demonstrates calling fork
and continuing on two different parallel branches based on its result value:
import { BaseAgent, agent } from '@golemcloud/golem-ts-sdk';
import { fork, type ForkResult } from "golem:api/host@1.1.7"
@agent()
class ExampleAgent extends BaseAgent {
name: string;
constructor(name: string, mode: "root" | "fork") {
super();
this.name = name;
}
run() {
switch (fork(`example-agent("${this.name}",fork)`)) {
case "original": {
// ...
break;
}
case "forked": {
// ...
break;
}
}
}
}