Quickstart
Build and run your first Lucid agent in 5 minutes.
This guide walks you through creating a working agent in under 5 minutes.
Create your agent
Run the CLI to scaffold a new project:
bunx @lucid-agents/cli my-agentSelect the following options when prompted:
- Adapter:
hono(lightweight HTTP server) - Template:
blank(minimal starter) - Configuration: Enter your agent name and description
Or use inline configuration:
bunx @lucid-agents/cli my-agent \
--adapter=hono \
--template=blank \
--AGENT_NAME="My First Agent"Start the development server
cd my-agent
bun run devYour agent is now running at http://localhost:3000.
Test your agent
Open a new terminal and try these commands:
View the agent manifest
curl http://localhost:3000/.well-known/agent.jsonThis returns the Agent Card describing your agent's capabilities, entrypoints, and metadata.
List available entrypoints
curl http://localhost:3000/entrypointsInvoke an entrypoint
For the blank template, invoke the echo entrypoint:
curl -X POST http://localhost:3000/entrypoints/echo/invoke \
-H "Content-Type: application/json" \
-d '{"input": {"text": "Hello, Lucid Agents!"}}'Understanding the project structure
The CLI generates a project with this structure:
my-agent/
├── src/
│ ├── agent.ts # Agent definition and entrypoints
│ └── index.ts # HTTP server bootstrap
├── .env # Environment variables
├── package.json
└── tsconfig.jsonOpen src/agent.ts to see your agent definition:
import { z } from 'zod';
import { createAgent } from '@lucid-agents/core';
import { http } from '@lucid-agents/http';
import { payments, paymentsFromEnv } from '@lucid-agents/payments';
const agent = await createAgent({
name: process.env.AGENT_NAME ?? 'my-agent',
version: process.env.AGENT_VERSION ?? '0.1.0',
description: process.env.AGENT_DESCRIPTION,
})
.use(http())
.use(payments({ config: paymentsFromEnv() }))
.build();
agent.entrypoints.add({
key: 'echo',
description: 'Echo back a message',
input: z.object({
text: z.string(),
}),
output: z.object({
echoed: z.string(),
timestamp: z.string(),
}),
async handler({ input }) {
return {
output: {
echoed: input.text,
timestamp: new Date().toISOString(),
},
};
},
});Add a streaming entrypoint
You can add streaming behavior after the scaffold is up. Add this after the existing entrypoint:
agent.entrypoints.add({
key: 'status-stream',
description: 'Streams a few status updates',
input: z.object({
topic: z.string(),
}),
output: z.object({
completed: z.boolean(),
}),
streaming: true,
async stream({ input }, emit) {
await emit({
kind: 'delta',
delta: `Starting work on ${input.topic}\n`,
mime: 'text/plain',
});
await emit({
kind: 'delta',
delta: 'Still working...\n',
mime: 'text/plain',
});
return { output: { completed: true } };
},
});Test it:
curl -X POST http://localhost:3000/entrypoints/status-stream/stream \
-H "Content-Type: application/json" \
-d '{"input": {"topic": "a quick demo"}}'Response events will stream over Server-Sent Events, followed by the final result payload.
What's next?
You now have a working agent. From here you can:
Learn about agents
Understand agent configuration and lifecycle
Learn about entrypoints
Define typed capabilities with schemas
When you're ready to add more capabilities:
- Accept payments - See the Payments package
- On-chain identity - See the Identity package
- Call other agents - See the A2A package