Emend
Build

Searching Learned Context

Use unified search, profile search, and playbook search to retrieve the right Emend context for your agent.

Search is how your agent turns Emend's learned context back into runtime behavior. Use unified search for most agent turns, then use profile or playbook search directly when you need a narrower workflow.

API reference
For complete parameters, response schemas, and cURL payloads, use the Unified Search API Reference, Profiles API Reference, and Playbook API Reference.

Which Search Should I Use?

WhenMethodCallDescriptionReturns
Default for agent turnsUnified searchclient.searchRetrieves profiles, agent playbooks, and user playbooks together so your agent can build complete prompt context in one call.All learned context types
User memoryProfile searchclient.search_user_profilesFinds durable user facts, preferences, goals, constraints, and other profile memory for a specific user.User profiles
Per-interaction lessonsUser playbook searchclient.search_user_playbooksFinds raw user-level playbook signals when you need to inspect evidence, debug behavior, or review recent lessons.User playbooks
Reusable behavior rulesAgent playbook searchclient.search_agent_playbooksFinds consolidated agent guidance, usually filtered to approved playbooks for production prompt context.Agent playbooks

Unified search is usually the best default because it searches the three learned context types in parallel. Entity-specific search is better for review screens, debugging, audits, or workflows that only need one type of result.

Unified Search

Unified search calls /api/search and fans out across profiles, user playbooks, and agent playbooks. top_k applies per entity type, so top_k=3 can return up to three profiles, three user playbooks, and three agent playbooks.

API reference: client.search.

When an agent playbook represents one or more source user playbooks, Emend omits those represented user playbooks from the user_playbooks result to avoid injecting duplicate guidance.

from emend import EmendClient client = EmendClient()  # uses EMEND_API_KEY env var results = client.search(    query="customer wants a concise answer about billing dispute next steps",    user_id="customer_123",    agent_version="support-agent@2026-06-21",    source="api",    tags=["billing", "support"],    top_k=4,    threshold=0.35,    agent_playbook_status_filter=["approved"],) profile_context = "\n".join(f"- {profile.content}" for profile in results.profiles)agent_playbook_context = "\n".join(    f"- {playbook.content}" for playbook in results.agent_playbooks)user_playbook_context = "\n".join(    f"- {playbook.content}" for playbook in results.user_playbooks) system_context = f"""User profiles:{profile_context or "- No matching profiles."} Approved agent playbooks:{agent_playbook_context or "- No matching agent playbooks."} Recent user-specific playbook signals:{user_playbook_context or "- No matching user playbooks."}""".strip()

Unified tags are shared across the selected entity types and use OR semantics: an item tagged billing matches tags=["billing", "support"] even when it does not also have the support tag. Omit tags, pass null, or pass [] to disable tag filtering.

Unified source is also shared across selected entity types and uses exact matching. Profiles and user playbooks compare their stored source; agent playbooks match through any linked source user playbook. Omit source, pass null, or pass an empty string to disable this filter.

Report the Context You Injected

Recommended: whenever you inject Emend context, attach its stable IDs to the resulting assistant turn as retrieved_learnings. This is how Emend can measure retrieval quality, including irrelevant or harmful context that the answer never cites. Search alone does not record what reached the model.

Continue the Python example above after applying any filtering or token-budget selection to results. Build both system_context and these references from the same retained items:

from emend import InteractionData retrieved_learnings = [    *({"kind": "profile", "learning_id": p.profile_id} for p in results.profiles),    *({"kind": "user_playbook", "learning_id": str(p.user_playbook_id)}      for p in results.user_playbooks),    *({"kind": "agent_playbook", "learning_id": str(p.agent_playbook_id)}      for p in results.agent_playbooks),]user_message = "What should I do about this billing dispute?"# Replace call_your_llm with your application's model call.answer = call_your_llm([    {"role": "system", "content": system_context},    {"role": "user", "content": user_message},])client.publish_interaction(    user_id="customer_123",    session_id="billing_session_001",    agent_version="support-agent@2026-06-21",    interactions=[        InteractionData(role="User", content=user_message),        InteractionData(role="Agent", content=answer,                        retrieved_learnings=retrieved_learnings),    ],    retrieval_experiment_id=(results.experiment.experiment_id if results.experiment else None),    retrieval_experiment_arm=(results.experiment.arm if results.experiment else None),)

Use profile_id, user_playbook_id, and agent_playbook_id from the returned objects; numeric IDs become strings. Include all injected learnings, not only those claimed in citations. Exclude search results discarded before prompt construction. Omit the field or send [] if no learning was injected, including an experiment holdout response.

Next, grade the session and read learning verdicts. The Evaluation dashboard groups these verdicts by response to show relevance, impact, and coverage.

Narrow Unified Search

Use entity_types when you want the unified search behavior, query reformulation, and shared filters, but only need some result types.

profile_and_agent_guidance = client.search(    query="how should we answer this premium user about renewal?",    user_id="customer_123",    agent_version="support-agent@2026-06-21",    entity_types=["profiles", "agent_playbooks"],    agent_playbook_status_filter=["approved"],    top_k=5,)

Use enable_reformulation=True when the user's latest message depends on recent conversation context. Pass conversation_history so Emend can rewrite the query before retrieval.

results = client.search(    query="what should I say next?",    user_id="customer_123",    conversation_history=[        {"role": "user", "content": "I was charged twice for my plan."},        {"role": "assistant", "content": "I can help check the invoice."},    ],    enable_reformulation=True,    top_k=3,)

Profile Search

Profile search is scoped to one user_id. Use it when you only need durable facts, preferences, goals, constraints, or user-specific memory.

API reference: client.search_user_profiles.

profiles = client.search_user_profiles(    user_id="customer_123",    query="billing preferences communication style",    tags=["billing"],    top_k=5,    threshold=0.6,) for profile in profiles.user_profiles:    print(profile.content)

Profile search also supports filters such as source, custom_feature, generated_from_request_id, start_time, end_time, tags, and search_mode.

User Playbook Search

User playbooks are interaction-level lessons extracted from a user's actual experience. Search them when you want to inspect the evidence behind behavior changes, find recent user-specific signals, or debug why an aggregated agent playbook exists.

API reference: client.search_user_playbooks.

user_playbooks = client.search_user_playbooks(    query="billing disputes require concise next steps",    user_id="customer_123",    agent_version="support-agent@2026-06-21",    source="api",    tags=["billing"],    top_k=10,) for playbook in user_playbooks.user_playbooks:    print(playbook.request_id, playbook.content)

Use user playbook search for investigation and review. For production prompt injection, prefer unified search or approved agent playbook search so your agent does not overfit to a single interaction.

source is an exact producer/workflow label filter and is applied before ranking and top_k. Omit it or pass an empty string to search all sources.

Agent Playbook Search

Agent playbooks are consolidated rules intended to guide the agent across users. Search them when you want reusable behavior guidance, especially approved playbooks for production traffic.

API reference: client.search_agent_playbooks.

agent_playbooks = client.search_agent_playbooks(    query="billing disputes require concise next steps",    user_id="customer_123",    agent_version="support-agent@2026-06-21",    source="api",    playbook_status_filter="approved",    tags=["billing"],    top_k=5,) for playbook in agent_playbooks.agent_playbooks:    print(playbook.playbook_name, playbook.content)

For agent-facing context, filter to approved playbooks unless you intentionally want to preview pending or rejected guidance in an internal review workflow.

Agent playbooks do not store a single source value: source="api" matches when at least one linked source user playbook has the exact api source.

When status_filter is omitted, agent playbook search includes lifecycle-current and lifecycle-pending rows; pass an explicit filter to select a different set.

Info
When a retrieval experiment is active, all four learning-search APIs require a stable user_id for agent traffic. The response's experiment field tells you which arm served the request. Holdout responses are successful and empty; echo the returned experiment ID and arm when publishing the resulting interaction.

Search Modes and Tags

Use search_mode when you need explicit retrieval behavior, and use tags to keep retrieval aligned to a product area, workflow, or domain.

SettingUse whenExample
search_mode="hybrid"Default when hybrid search is configured. You want both semantic similarity and keyword matching.search_mode="hybrid"
search_mode="vector"Conceptual retrieval. The query is conceptual and does not depend on exact keywords.search_mode="vector"
search_mode="fts"Keyword retrieval. Exact terms, identifiers, or product names matter more than semantic similarity.search_mode="fts"
tagsDomain filtering. Match profiles, user playbooks, or agent playbooks that have any requested tag.tags=["billing", "support"]

Practical Defaults

  • Start with client.search for agent turns.
  • Pass user_id whenever the result should include user profiles or user-level playbooks.
  • Pass agent_version when searching playbooks for a specific deployed agent version.
  • Use agent_playbook_status_filter=["approved"] or playbook_status_filter="approved" for production prompt context.
  • Keep top_k small enough that the retrieved context fits your model prompt.
  • Publish the injected subset as retrieved_learnings and inspect relevance, negative impact, and ungraded results before changing retrieval settings.
  • Omit threshold to use the default for the configured embedding route. A Custom enterprise service applies its operator-selected model policy automatically.
  • Lower threshold if useful context is missing; raise it if results are noisy.
  • When a query explicitly asks Emend not to use profiles, preferences, memory, or other personalized context, high-precision English and Chinese detection automatically suppresses profiles and user playbooks for that search.

Search text is Unicode-normalized. Chinese, Japanese, Arabic, accented-Latin, and mixed-script queries participate in both semantic and lexical retrieval. When reformulation is enabled, Emend preserves the query's source language and writing system unless the user explicitly asks for translation.