Agentic Affinity Alignment
Keep an agent's generated responses aligned with a specific user's taste using a score, generate, refine loop.
Any agent that generates responses for a specific user can keep those responses aligned with the user's taste by scoring candidates against the user before replying.
Who this is for
Any agent generating responses to a user: chat agents, writing agents, recommendation agents, creative agents.
The loop
Today the "score candidates against the user" step uses POST /v1/rerank. A dedicated single-candidate scoring endpoint (/v1/score) is planned; see the callouts at the bottom.
Copy-paste walkthrough
export API_KEY="galya_..."
export USER_ID="shopper_jordan"
export BASE="https://api.galya.io/v1"1. Create the user
curl -sS -X POST "$BASE/entity" \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"id": "'"$USER_ID"'",
"type": "user",
"name": "Jordan",
"description": "Coastal minimalist."
}'2. Link content the user has interacted with
Each interaction becomes one POST /v1/index call with entity_id set to the user. entity_id in the request body is the user's id (the link target); the response's entity_id is a hashed id for the content item itself.
curl -sS -X POST "$BASE/index" \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": {
"url": "https://store.example/oak-credenza",
"type": "text",
"content": "Low oak credenza, linen front, coastal minimalist.",
"skip_url_fetch": true
},
"entity_id": "'"$USER_ID"'"
}'3. Generate N candidate responses
Your agent produces N candidate responses however it normally does. Represent each candidate as inline text content so it can be sent straight to /rerank without being persisted as a real catalog item:
[
{
"url": "agent://candidate-1",
"type": "text",
"content": "Response option 1 text goes here.",
"skip_url_fetch": true,
"skip_media_enrich": true
},
{
"url": "agent://candidate-2",
"type": "text",
"content": "Response option 2 text goes here.",
"skip_url_fetch": true,
"skip_media_enrich": true
}
]4. Rank candidates against the user's taste
curl -sS -X POST "$BASE/rerank?relative_to_entity_id=$USER_ID&in_terms_of_entity_type=content" \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"candidates": [
{
"url": "agent://candidate-1",
"type": "text",
"content": "Response option 1 text goes here.",
"skip_url_fetch": true,
"skip_media_enrich": true
},
{
"url": "agent://candidate-2",
"type": "text",
"content": "Response option 2 text goes here.",
"skip_url_fetch": true,
"skip_media_enrich": true
}
]
}'Response 200, best match first:
{
"results": [
{
"id": "…",
"name": "…",
"description": "Response option 2 text goes here.",
"type": "content",
"linked_content": [],
"linked_entities": []
},
{
"id": "…",
"name": "…",
"description": "Response option 1 text goes here.",
"type": "content",
"linked_content": [],
"linked_entities": []
}
]
}5. Loop or respond
The top result is the best-aligned candidate for this user's taste. If your agent needs a numeric threshold, that is what the coming-soon /v1/score endpoint is for; today, treat the first element of results as the winner and, if you want more variety, regenerate and rerank again.
Coming soon
/v1/score — coming soon
A single-content + single-user endpoint that returns a numeric score. Use this for threshold-driven loops. Today, POST /v1/rerank returns rank order only; scores are not exposed.
/v1/explain optional prompt field — coming soon
POST /v1/explain will accept an optional prompt field so an agent can request a taste-aligned nudge (e.g. "rewrite this to fit their palette"). Today, only query is read.
Validators package — coming soon
A validators package for enforcing taste-alignment thresholds inside agent runtimes is planned.
/taste-align skill — coming soon
A /taste-align skill is planned in the main skills repo. See the Skills page for context.