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:
profilefor owner identity, persona, and social linksprojectsfor project writeups and project catalog toolsexperiences,education,awards, andskillsfor resume grounding- card types such as
project,experience, andeducation
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:
| Surface | Contract |
|---|---|
| Request | POST /api/chat with either messages or message plus optional history |
| Stream | Server-Sent Events from /api/chat |
| UI hints | Generic cards and links payloads |
| Knowledge | Markdown files under vault/ |
| Persona | vault/profile/persona.md |
| Owner label | name in vault/profile/about.md, falling back to the portfolio owner |
| Runtime settings | Admin 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.
| Event | Purpose |
|---|---|
item | Registers the assistant response anchor |
step_start / step_delta / step_end | Tool and reasoning timeline events |
thinking_text | Provider thinking text when enabled |
token | Final answer text deltas |
ui | Generic card and link hints |
attachment | Optional debug payload when debug: true |
error | Streamable error payload |
done | Completion 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 type | Current renderer |
|---|---|
project | Project card |
experience | Resume experience list |
education | Resume 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
typeforcards[].type. - Use the vault frontmatter
slugwhen present, otherwise useid. - Use
links[].idfor 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:
- Replace
vault/profile/about.mdwith the owner name, role, location, and profile links. - Replace
vault/profile/persona.mdwith the new voice and behavior spec. - Add Markdown records for the entity types the site wants to expose.
- Make sure each renderable record has frontmatter with
typeand eitherslugorid. - Build or replace tools for any structured catalog operations beyond generic vault search.
- Map
ChatUiHints.cardstypes to the consuming site's card components. - 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, andeducationcards 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.
