Quickstart
Get a hello-world agent talking to AgentPack in about ten minutes.
Prerequisites
- A Firebase project (free tier works). Grab its
project_refand a service role key. curlandjqon your machine.- One environment variable exported in your shell:
export AGENTPACK_URL="https://<project_ref>.firebaseapp.com/functions/v1"
export AGENTPACK_BRIDGE_KEY="<your-project-bridge-key>" #
1. Apply the migrations
cd deploy/firebase
firebase db push # or use the Firebase MCP / dashboard to apply
All eight schemas come up: identity, postbox, recall, mesh, gateway,
scheduler, artifacts, governor.
for detail on ordering and replay.
2. Deploy the Cloud Functions
From the repo root:
for fn in agent-identity agent-postbox agent-memory agent-mesh \
agent-gateway agent-scheduler agent-artifacts; do
firebase functions deploy "$fn" --no-verify-jwt
done
Each function uses custom auth (x-agentpack-key or
x-agentpack-device-key), not Firebase ID tokens — that's why --no-verify-jwt is
correct here.
3. Register your first agent and issue a device key
curl -s "$AGENTPACK_URL/agent-identity/device/issue" \
-H "x-agentpack-key: $AGENTPACK_BRIDGE_KEY" \
-H "content-type: application/json" \
-d '{"agent_id":"agent-hello","label":"laptop"}' | jq
You'll get back:
{
"id": "a1b2...",
"secret": "ap_dev_...",
"created_at": "2026-04-20T..."
}
Copy the secret now — it is shown exactly once. Export it:
export AGENT_DEVICE_KEY="ap_dev_..."
4. Send your agent its first email
First, allocate a mailbox address:
curl -s "$AGENTPACK_URL/agent-postbox/alloc" \
-H "x-agentpack-device-key: $AGENT_DEVICE_KEY" \
-H "content-type: application/json" \
-d '{"agent_id":"agent-hello","domain":"example.test"}' | jq -r '.addr'
# -> agent-hello.t-abc123@example.test
Then deliver a message via the project-only /ingest endpoint (this is what
your MTA calls):
curl -s "$AGENTPACK_URL/agent-postbox/ingest" \
-H "x-agentpack-key: $AGENTPACK_BRIDGE_KEY" \
-H "content-type: application/json" \
-d '{
"to": "agent-hello.t-abc123@example.test",
"from": "human@example.com",
"subject": "hello world",
"body": "welcome to AgentPack"
}' | jq
And read it back from the agent's perspective:
curl -s "$AGENTPACK_URL/agent-postbox/list" \
-H "x-agentpack-device-key: $AGENT_DEVICE_KEY" \
-H "content-type: application/json" \
-d '{"agent_id":"agent-hello","limit":5}' | jq
5. Write something to memory
curl -s "$AGENTPACK_URL/agent-memory/mem/write" \
-H "x-agentpack-device-key: $AGENT_DEVICE_KEY" \
-H "content-type: application/json" \
-d '{
"agent_id":"agent-hello",
"kind":"fact",
"text":"the user prefers concise answers",
"provenance":"user-direct-instruction",
"scope":["self"]
}' | jq
Query it back:
curl -s "$AGENTPACK_URL/agent-memory/mem/query" \
-H "x-agentpack-device-key: $AGENT_DEVICE_KEY" \
-H "content-type: application/json" \
-d '{"agent_id":"agent-hello","query":"response style","limit":3}' | jq
What just happened?
In a handful of HTTP calls you:
- Issued a cryptographic device key bound to an agent identity.
- Allocated a per-task mailbox and ingested an RFC-822 message.
- Stored a semantic fact and retrieved it by search.
Every call was logged to the hash-chained audit ledger, authorized by
identity.verify_device_key(), and scoped so that a leaked device key only
leaks one agent's data.
Next steps
- Core concepts — what agent, device, scope, delegation mean here
- Build your first agent — a 40-line TypeScript worker
- Architecture overview — how the pieces fit