Walkthrough
This is the whole Galya Beta in one sitting. You'll wire up a tiny retail catalog (a home-goods store), teach Galya one shopper's taste, and then query it.
The loop is always the same:
- Create a user: the person whose taste you're modeling.
- Index content linked to that user: the catalog items they like (
entity_iddoes the linking). - Compose: turn those linked items into the user's taste profile.
- Query:
search,rerank,ask,explain, and listclusters.
What you need
A base URL of https://api.galya.io/v1 and a workspace secret key (galya_wsk_…) sent as the X-API-Key header. See Setup & auth for where to get the key. Set it once:
export GALYA_API_KEY="galya_wsk_…"The #1 trap: query params, not body
search, rerank, ask, and explain need relative_to_entity_id and in_terms_of_entity_type in the URL query string — not the JSON body. Leave either out and you get:
{ "error": "relative_to_entity_id and in_terms_of_entity_type are required", "code": "bad_request" }Every example below shows them in the URL. relative_to_entity_id is "whose taste," in_terms_of_entity_type is "what kind of thing to rank" (here, content).
Install the SDK (optional)
Every step shows curl and the @galya/agents TypeScript client. If you want the SDK:
npm install @galya/agentsimport { GalyaApiClient } from "@galya/agents";
const api = new GalyaApiClient({ apiKey: process.env.GALYA_API_KEY! });Run the whole thing
Save this as walkthrough.mts, then run it. It does every step above end to end.
npm install @galya/agents
npm install -D tsx # if you don't have a TypeScript runner
export GALYA_API_KEY="galya_wsk_…"
npx tsx walkthrough.mtsFull runnable script (walkthrough.mts)
import { GalyaApiClient } from "@galya/agents";
const api = new GalyaApiClient({ apiKey: process.env.GALYA_API_KEY! });
const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
async function main() {
const userId = `shopper_jordan_${Date.now()}`;
// 1. Create the user (the taste anchor). Returns HTTP 200.
const user = await api.createEntity({
id: userId,
type: "user",
name: "Jordan",
description: "Likes calm, coastal, minimalist rooms — natural oak, linen, muted sand and white.",
});
console.log("user:", user.entity_id);
// 2. Index catalog items LINKED to the user via entity_id.
const catalog = [
{ url: `https://store.example/oak-credenza-${userId}`, content: "Low oak credenza, sand-toned linen front, soft coastal minimalist living room." },
{ url: `https://store.example/linen-sofa-${userId}`, content: "Off-white linen slipcover sofa, airy bright room, natural materials, calm palette." },
{ url: `https://store.example/brass-lamp-${userId}`, content: "Warm brass task lamp, muted neutral desk, understated minimalist workspace." },
];
for (const item of catalog) {
const r = await api.indexContent({
content: { url: item.url, type: "text", content: item.content, skip_url_fetch: true },
entity_id: user.entity_id,
});
console.log("indexed:", r.entity_id, "created:", r.created);
}
// Give link writes a moment to settle before composing.
await sleep(5000);
// 3. Compose the user's taste profile.
const composed = await api.composeEntity(user.entity_id);
console.log("composed:", composed.entity_id);
// 4a. Search the catalog by taste (query params in the URL).
const { results } = await api.search(
{ relativeToEntityId: user.entity_id, inTermsOfEntityType: "content" },
{ query: "calm coastal furniture in natural materials" },
);
console.log("search:", results.map((r) => r.id));
// 4b. Rerank a shortlist (no history required).
const reranked = await api.rerank(
{ relativeToEntityId: user.entity_id, inTermsOfEntityType: "content" },
{
candidates: [
{ url: `https://store.example/walnut-desk-${userId}`, type: "text", content: "Dark glossy walnut executive desk, ornate, maximalist." },
{ url: `https://store.example/linen-chair-${userId}`, type: "text", content: "Natural linen lounge chair, pale oak frame, airy minimalist." },
],
},
);
console.log("rerank:", reranked.results.map((r) => r.id));
// 4c. Ask a taste-personalized question.
const askRes = (await api.ask(
{ relativeToEntityId: user.entity_id, inTermsOfEntityType: "content" },
{ query: "Recommend a sofa for my living room and say why it fits my taste." },
)) as { answer: { content: { text: string }[] } };
console.log("ask:", askRes.answer.content[0]?.text);
// 4d. Explain the user's taste.
const { explanation } = await api.explain(
{ relativeToEntityId: user.entity_id, inTermsOfEntityType: "content", domain: "design", task: "design-agent" },
{ query: "Summarize this shopper's furniture taste: palette, materials, silhouette." },
);
console.log("explain:", explanation);
// 5. List taste clusters.
const { results: clusters } = await api.listClusters({ entityType: "content", limit: 20 });
console.log("clusters:", clusters.length);
}
main().catch((e) => {
console.error(e);
process.exit(1);
});