Skip to content

chat() context: entity is typed as a string but read as an object, silently stamping undefined/undefined #56

Description

@mgoldsborough

Summary

The entity field on the chat context is typed as a string in the SDK but read as an object by the NimbleBrain host, so anything passed there reaches the agent as the literal text entity: undefined/undefined.

The mismatch

SDK — entity is a string:

// src/types.ts:379
chat(message: string, context?: { action?: string; entity?: string }): void;
// src/types.ts:594 — same shape on the vanilla API
sendMessage(text: string, context?: { action?: string; entity?: string }): void;

Host — reads two properties off it:

// NimbleBrainInc/nimblebrain, web/src/components/AppWithChat.tsx:161
if (context.entity) parts.push(`entity: ${context.entity.type}/${context.entity.id}`);

A string passes the truthiness check, so there is no error and no warning — .type and .id are both undefined and the App Context prefix the model receives reads entity: undefined/undefined.

Reproduce

const chat = useChat();
chat("Tell me about this row", { entity: "example.com" });
// model receives: [App Context: <app> | entity: undefined/undefined]
//                 Tell me about this row

Why it matters

entity is the natural place to carry which row/record an interaction is about, and it is the field an app author reaches for first. Today it silently drops that identity — the only symptom is degraded model context, which no test or type check surfaces. Apps currently have to put the identity in the prompt text instead.

Which side is wrong

Deliberately not asserting one, since it is a contract decision:

  • If the object shape is canonical, the SDK types (types.ts:379 and :594) are stale and should be { type: string; id: string }.
  • If the string shape is canonical, the host's read is wrong and should treat entity as an opaque label.

The host's own UiChatContext already declares the object form, which is weak evidence the SDK type is the stale one — but the SDK is consumed by hosts other than NimbleBrain, so the naming/shape choice is worth an explicit call rather than a silent alignment.

Whichever way it lands, a type that cannot be passed incorrectly would be an improvement over one where the wrong shape compiles.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions