Skip to main content
plannedCofounder, Percena · Integrator on this siteJul 2026 — Present

Agent Brief Desk — a Weft agent that drives this site's API

An agent workspace built into this portfolio with the Weft SDK — an LLM agent builds a hiring brief by driving the site's own OpenAPI, behind a state machine that refuses illegal steps.

Disclosure

I'm a cofounder of Percena, and Weft is our product — so I'm not a neutral reviewer of it. I didn't write the SDK. My part in Weft is product direction, ideas, and marketing; on this site I'm the integrator. That split is the point of this write-up: it's the first time I've had to use the thing I help shape, and the integration is where product opinions meet a real codebase.

Overview

This portfolio has three modes. Human is the site you're reading. Machine is an llms.txt-style overlay for crawlers — passive, read-only. Agent is a real workspace: a Weft-powered agent that builds a hiring brief by calling this site's own API.

The pitch in one line:

Human for people, Machine for crawlers, Agent for operators.

You give it an intent ("I'm hiring for an agent-memory role"), and it shortlists projects and posts from the actual content, drafts a brief, and hands you exportable markdown. It's not a chatbot bolted onto a marketing page — it does not answer questions about the site, it operates on it, through the same HTTP endpoints you could curl.

Why build it this way

A chatbot on a portfolio proves nothing; it's a text box in front of a model that has read your homepage. The interesting claim is narrower and harder: can an agent be given a real, stateful product surface and be trusted not to wreck it?

So the demo is deliberately unglamorous. The agent doesn't "vibe navigate." It mutates a session artifact through explicit transitions, and the backend is the authority on which ones are legal.

How it works

Three trust domains, fail-closed:

  BROWSER                   THIS SITE                 CONTROL PLANE
  (untrusted)               (trusted)                 (weftd)
  +------------------+      +------------------+      +-------------+
  | Weft chat panel  |      | holds dev key,   |      | brokers the |
  |                  |-ask->| mints scoped     |-key->| LLM run     |
  | scoped token     |<-tok-| sessions         |      |             |
  | only             |      |                  |      |             |
  +-------+----------+      +------------------+      +-----^-------+
          |                                                 |
          |   REST + SSE, via the                           |
          +---same-origin /api/weft proxy ------------------+
          |   (strips cookies, allowlists headers)
          |
          | client-executed tools: same-origin, your cookie
          v
  +------------------------------------------------+
  | /api/v1/*  -- Brief Desk API                   |
  | every mutation runs the state machine;         |
  | illegal step -> 409 { error, allowed_actions } |
  +------------------------------------------------+

The pieces worth naming:

The developer key never reaches the browser. The backend mints a scoped session token; the browser gets only that. All browser↔control-plane traffic — including the SSE timeline — goes through a same-origin proxy that strips cookies and allowlists headers, so the guest session cookie never leaks to the control plane.

Tools come from an OpenAPI spec, not from prose. The toolset is derived from the site's own OpenAPI document, which means the agent's capabilities and the API's real contract cannot drift apart. Tools run execution: client — same-origin, from the browser, with the visitor's cookie — so the agent has exactly the permissions a visitor has, and nothing more.

A state machine is the backstop. The brief moves empty → scoping → collecting → drafted → ready → exported, with back-edges for revision. Ask it to submit a brief before anything is shortlisted and the API answers 409 with the list of allowed_actions. The agent relays that and recovers instead of blind-retrying. The system prompt is rendered from the same state-machine module the API enforces, so the model's instructions and the server's rules can't disagree.

The agent shows its work. Tool calls appear as named steps in a timeline rather than a black-box answer bubble, and an action bridge highlights the exact card or row a tool just touched — so you can watch a shortlist item land where the agent said it landed.

Approval gates. Permission mode defaults to ask: the agent can draft a contact message, but sending requires a human to approve it in the chat.

What I'd flag if you asked me hard questions

Honest limits, because a case study that only lists wins isn't worth much:

  • State is in-memory, per instance. A multi-instance deployment can lose a brief mid-session. That's a deliberate v1 trade for a portfolio demo, not a design I'd defend for a real product; a KV store is the obvious next step.
  • Agent mode is flag-gated and off by default. It needs control-plane credentials to run, and Human mode is built to work with none of it present — the portfolio must never depend on the agent stack being up.
  • Rate limits are basic. Per-IP fixed windows, body caps, bounded event streams. Proportional to a personal site, not a WAF.
  • The abuse surface is real. A public site fronting an LLM runtime can burn a token budget. Anything that says an action came from an agent is a label, never an authorization signal — the browser can set it.

Status, and how to try it

In development, behind a feature flag. The domain API, the desk UI, the action bridge, and the tool wiring are built and tested; the local protocol has been verified end-to-end against a stand-in control plane.

Agent mode is gated on NEXT_PUBLIC_AGENT_BRIEF and hidden by default — when it's off, the mode switcher offers Human and Machine only, and none of the agent JavaScript is downloaded. Turning it on also needs server-side control-plane credentials (WEFTD_BASE, WEFT_API_KEY, WEFT_TENANT_ID); without them the chat fails closed with a clear error instead of half-working. The SDK itself is at percena/weft-sdk.