Agent / Expose, do not reimplement
The mental model
There are four different values in normal agent code. Keeping them separate makes the API much easier to read:
Foldkit application
App
|
| Agent.forApplication(App)
v
application-specialized builder
AgentBuilder
|
| .make(...)
v
protocol-neutral contract
AssistantAgent
|
| .bind({ host })
v
live AgentRuntime
|
+--> WebMCP
+--> MCP
+--> A2A
+--> Agent NativeA useful naming rule is builder first, contract second:
ts
const AgentBuilder = Agent.forApplication(App).withPrincipal<Principal>()
const AssistantAgent = AgentBuilder.make({
// ...the actual agent contract
})AgentBuilder is not an agent. It is a typed DSL specialized to this
application's Model, Message union, and Principal type. Its helpers such as
make, expose, and bind now know those types.
AssistantAgent is the actual contract: what this agent may see, what it may do,
which policies apply, how completion is recognized, and which read-only
resources it exposes. This is the value adapters describe and serve.
Binding that contract to a running application produces the live runtime that can read the current Model and dispatch Messages.