Skip to content

Instantly share code, notes, and snippets.

@aelfannir
Last active March 13, 2026 15:22
Show Gist options
  • Select an option

  • Save aelfannir/f62bd492faca83c271c5aacfd2d598a2 to your computer and use it in GitHub Desktop.

Select an option

Save aelfannir/f62bd492faca83c271c5aacfd2d598a2 to your computer and use it in GitHub Desktop.
AI Structured Data Card Format — standard format for all AI outputs (recommendations, chat, etc.)

Chat AI — Structured Data Format (SSE)

When the AI presents entities to the guest in chat, it streams JSON-LD objects from our API as SSE events. The frontend renders cards as they arrive using @type to pick the component.

Why This Approach

  • No custom format: standard API Platform JSON-LD responses — same shape the frontend already handles
  • Progressive rendering: cards appear one by one as the AI streams them
  • Scalable: any entity from our API works. New entity types or fields are picked up automatically.
  • Conversation storage: structured data is stored as-is. Old conversations keep the original data as a snapshot.

The ?info=true Parameter

Use ?info=true when fetching entities. This returns a minimal, card-friendly representation.

When the AI decides which entities to return:

  • If the data was already fetched with ?info=true during reasoning → pass it through as-is
  • Otherwise → fetch the identified IRIs with ?info=true before returning them

Return the JSON-LD objects as-is. Do not transform or cherry-pick fields.

SSE Event Types

Event Description
text AI-generated chat text
resource Any entity from our API
done End of response

One object per SSE event. Each resource event contains a single JSON-LD object. When returning multiple entities, send one resource event per entity — do not batch them into arrays.

Example

event: text
data: "Here are some great options for tonight:"

event: resource
data: {"@id":"/restaurants/rt_ghi789","@type":"Restaurant","identifier":"rt_ghi789","name":"Le Jardin","cuisine":"Mediterranean"}

event: resource
data: {"@id":"/restaurants/rt_abc123","@type":"Restaurant","identifier":"rt_abc123","name":"La Terrasse","cuisine":"Italian"}

event: resource
data: {"@id":"/activities/act_jkl012","@type":"Activity","identifier":"act_jkl012","name":"Sunset Yoga Session","description":"Guided yoga on the beach at golden hour"}

event: done
data: {}
@mouadayoub7221
Copy link

Hey Abderhamane kidayr cv, I added structured data streaming to the AI chat when the AI returns a list of entities
(restaurants, services, etc.), it now fetches each one with ?info=true and streams them as SSE
resource events so the frontend can render cards.

It works for all endpoints except /activities/{id} — guest JWT gets 422 without X-Hotel and 403 with
JWT + X-Hotel. So right now for activities, I'm falling back to the raw grouped data from
/activity_variants (which works with guest JWT), meaning the activity resource cards are heavier than
they should be.

I documented everything here: mymate-ai-main/ai_docs/api_problems/activity_info_blocked.md — includes
all endpoints tested with ?info=true and what each returns.

Do you want to open up GET /activities/{id} for guest JWT (at least with ?info=true)? If you do,
activities will automatically get minimal cards like everything else — no changes needed on my side.
Otherwise we keep the current fallback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment