docs/features/chat/agent-api.md

Chat Agent API

The chat agent is an opinionated portfolio chatbot starter, not a general-purpose agent SDK. It packages the common pieces a personal portfolio chatbot needs: a profile/persona vault, project and resume-oriented tools, streamed answers, and UI hints for portfolio cards.

The reusable part is intentionally small. Another personal site can swap the vault content, persona, model settings, and card renderers while keeping the portfolio-oriented defaults.

What Is Opinionated

This package assumes a portfolio-style knowledge base:

  • profile for owner identity, persona, and social links
  • projects for project writeups and project catalog tools
  • experiences, education, awards, and skills for resume grounding
  • card types such as project, experience, and education

Those assumptions are the fast path. Sites that need different entity types can still add new card renderers or replace structured catalog tools, but the default setup is optimized for portfolio chatbots.

Stable Boundary

Consumers should treat these pieces as the public integration surface:

SurfaceContract
RequestPOST /api/chat with either messages or message plus optional history
StreamServer-Sent Events from /api/chat
UI hintsGeneric cards and links payloads
KnowledgeMarkdown files under vault/
Personavault/profile/persona.md
Owner labelname in vault/profile/about.md, falling back to the portfolio owner
Runtime settingsAdmin settings store for harness, provider, models, and iteration cap

Everything else is an implementation detail of this site.

Request Shape

type ChatTurn = {
  role: 'user' | 'assistant';
  content: string;
};

type ChatRequest =
  | {
      messages: ChatTurn[];
      responseAnchorId?: string;
      debug?: boolean;
    }
  | {
      message: string;
      history?: ChatTurn[];
      debug?: boolean;
    };

messages is the browser UI shape. message plus history is useful for eval scripts and direct integrations.

Stream Events

The API emits SSE events. Consumers can ignore anything they do not render.

EventPurpose
itemRegisters the assistant response anchor
step_start / step_delta / step_endTool and reasoning timeline events
thinking_textProvider thinking text when enabled
tokenFinal answer text deltas
uiGeneric card and link hints
attachmentOptional debug payload when debug: true
errorStreamable error payload
doneCompletion marker

UI Hint Contract

The agent exposes generic UI hints. A consuming site decides how to render each card type.

type ChatUiCardHint = {
  type: string;
  slug: string;
  label?: string;
};

type ChatUiLinkHint = {
  id: string;
  label?: string;
  url?: string;
  blurb?: string;
};

type ChatUiHints = {
  cards: ChatUiCardHint[];
  links: ChatUiLinkHint[];
};

Example ui event:

{
  "type": "ui",
  "ui": {
    "cards": [
      { "type": "education", "slug": "iowa-state-university" },
      { "type": "experience", "slug": "workiva-software-engineer-intern" }
    ],
    "links": [{ "id": "github" }, { "id": "demo", "label": "Demo", "url": "https://example.com/demo" }]
  }
}

This portfolio currently renders:

Card typeCurrent renderer
projectProject card
experienceResume experience list
educationResume education list

Other sites can add their own card types, such as case-study, publication, product, service, or event, without changing the agent loop.

Agent Tool Contract

The model calls set_ui_hints once before the final answer:

{
  "cards": [{ "type": "project", "slug": "clanky" }],
  "links": [{ "id": "github" }]
}

Rules for agents:

  • Only surface cards grounded in files or tool results used for the answer.
  • Use the vault frontmatter type for cards[].type.
  • Use the vault frontmatter slug when present, otherwise use id.
  • Use links[].id for known profile links.
  • Use direct { id, label, url } links when the link is not part of the profile link registry.

Porting Checklist

To reuse this agent for another person:

  1. Replace vault/profile/about.md with the owner name, role, location, and profile links.
  2. Replace vault/profile/persona.md with the new voice and behavior spec.
  3. Add Markdown records for the entity types the site wants to expose.
  4. Make sure each renderable record has frontmatter with type and either slug or id.
  5. Build or replace tools for any structured catalog operations beyond generic vault search.
  6. Map ChatUiHints.cards types to the consuming site's card components.
  7. Rebuild the vault vector store after changing vault content.

Current Portfolio Adapter

The reusable layer is the agent contract. The current site still includes a portfolio adapter:

  • project, experience, and education cards hydrate existing portfolio components.
  • Profile link ids resolve through generated profile data.
  • Project catalog tools are portfolio-specific and can be replaced by another site's structured catalog tools.

That split lets the same agent loop serve other personal sites without hardcoding the owner or persona in the server prompt.