Icepick does not enforce a specific project structure, but some of the tooling assumes a certain project structure to make it easier to develop agents and tools. The recommended structure for a Icepick application is to have a single entrypoint that imports your agents and tools, and starts the Icepick client.
my-app/
├── src/
│   ├── agents/
│   │   ├── simple.agent.ts
│   │   └── index.ts
│   ├── tools/
│   │   ├── simple.tool.ts
│   │   └── index.ts
│   ├── main.ts
│   ├── icepick.client.ts
│   └── index.ts
├── package.json
└── tsconfig.json

Entrypoints

The minimal entrypoint for a Icepick application is a simple file that imports the icepick client, imports your agents and tools, and starts it.
// my-app/src/main.ts
import { icepick } from "@/icepick-client";

// Import tools to ensure they get registered
import "@/agents";
import "@/tools";

icepick.start();

Automatic Registration

In this example project, the my-app/src/agents/index.ts and my-app/src/tools/index.ts are barrel files that imports all the agents and tools in the my-app/src/agents and my-app/src/tools directories respectively.
// my-app/src/agents/index.ts
export * from "./simple.agent";
As you add more agents, tools, and toolboxes, you can add them to the barrel files and they will be automatically registered with the Icepick client.

Manual registration

For some more advanced use cases, you may want to manually register specific parts of your workload on multiple machines, for example cpu or memory bound work. For this you can use the register option on the icepick.start method.
// my-app/src/simple-agent.main.ts
import { icepick } from "@/icepick-client";
import { simpleAgent } from "@/agents/simple.agent";

icepick.start({
    name: "simple-agent"
    register: [
        simpleAgent,
    ]
});
This is further documented in the scaling documentation.