Project Structure
Understand how Agentuity projects are organized
Agentuity projects follow a convention-based structure that enables automatic discovery and deployment.
Just Add a Folder
Creating a new agent is as simple as adding a folder to src/agent/ with an agent.ts file. No CLI commands, no manual registration: agents are auto-discovered both locally and when deployed.
Directory Layout
my-project/
├── agentuity.json # Project configuration
├── .env # Environment variables
├── package.json # Dependencies
├── app.ts # App entry point
└── src/
├── agent/ # Agent code (required)
│ └── chat/
│ └── agent.ts # Agent logic
├── api/ # HTTP routes (optional)
│ └── index.ts # All routes, imports agents
└── web/ # Frontend code (scaffolded by default)
└── App.tsxAgent names come from their directory. Each agent has one file: agent.ts with your logic and schema.
Utility Files
You can add helper files (like types.ts, helpers.ts, utils.ts) alongside your agents and routes. The build system only processes files that export agents or routers.
Agents and Routes
Agents and routes are separate concerns in Agentuity:
| Concept | Location | Purpose |
|---|---|---|
| Agents | src/agent/ | Core logic, schemas, validation |
| Routes | src/api/ | HTTP endpoints, triggers (cron, WebSocket, SSE) |
Agents contain your core logic with schema validation and lifecycle hooks. Routes define how agents get invoked (HTTP, cron, webhooks, etc.). This separation keeps concerns clear: agents don't know how they're called, and routes handle all transport.
agent.ts
import { createAgent } from '@agentuity/runtime';
import { s } from '@agentuity/schema';
const agent = createAgent('Chat', {
schema: {
input: s.object({ message: s.string() }),
output: s.object({ response: s.string() }),
},
handler: async (ctx, input) => {
return { response: `Echo: ${input.message}` };
},
});
export default agent;src/api/index.ts
Routes import agents directly and call them:
import { createRouter } from '@agentuity/runtime';
import chat from '@agent/chat';
const router = createRouter();
router.post('/chat', chat.validator(), async (c) => {
const data = c.req.valid('json');
const result = await chat.run(data);
return c.json(result);
});
export default router;The chat.validator() middleware validates the request body against the agent's input schema and provides type-safe access via c.req.valid('json').
When to Use Agents vs Direct Routes
| Agents | Direct Routes (no agent) | |
|---|---|---|
| Location | src/agent/ | src/api/ |
| Schema validation | Built-in with agent.validator() | Manual |
| Events & Evals | Yes | No |
| Storage access | Full | Full |
| Best for | Validated workflows, LLM processing | Health checks, webhooks, simple endpoints |
Use simple routes (without calling an agent) for lightweight endpoints like health checks. For structured processing with validation, create an agent and call it from your route.
Frontend (src/web/)
Place frontend code in src/web/ to deploy alongside your agents. The CLI bundles and serves it automatically.
React is currently supported via @agentuity/react, with a framework-agnostic approach that enables support for Next.js, Svelte, and others.
// src/web/App.tsx
import { useAPI } from '@agentuity/react';
function App() {
const { data, invoke, isLoading } = useAPI('POST /api/hello');
return (
<button onClick={() => invoke({ name: 'World' })}>
{isLoading ? 'Loading...' : 'Say Hello'}
</button>
);
}Deployment Scenarios
You can also deploy your frontend elsewhere (e.g., Vercel, Netlify) and call your Agentuity agents via the React hooks with a configured baseUrl.
Next Steps
- App Configuration: Configure
app.tsandagentuity.json - Creating Agents: Deep dive into agent creation
- Routes: Learn about HTTP, cron, and other triggers
Need Help?
Join our Community for assistance or just to hang with other humans building agents.
Send us an email at hi@agentuity.com if you'd like to get in touch.
Please Follow us on
If you haven't already, please Signup for your free account now and start building your first agent!