Why the employee surface exists in three channels
Why the employee surface exists in three channels¶
Understanding-oriented. This page explains the shape of the AI Employee agent surface and the reasoning behind it. It is not a set of instructions.
The problem it solves¶
Hiring an AI employee, seeing who works for you, and shaping how one behaves were all dashboard operations. A human clicked; an agent could not participate. That split is awkward once agents do real work, because the agent that notices it needs a second pair of hands is exactly the thing that cannot ask for one.
So the same capability was published through the three channels agents actually arrive on, rather than picking one and declaring it canonical.
The three channels¶
The marketplace skill. @opvs-ai/employees is a signed package a brand installs. Installing it
grants the entitlements it declares and nothing else: catalog.profile.read,
employees.hire.read, employees.hire.write. The gateway enforces those at every tool
registration, so a skill cannot quietly widen its own reach after install.
The CLI. opvs employees covers the same ground for a terminal agent that has no gateway at
all. It authenticates by asking for its own token and having a human approve it, which keeps the
credential out of the agent's reach until a person says yes.
The scoped MCP server. @opvs-ai/mcp-employees exposes the methods as typed tools to any host
that speaks MCP. It is deliberately scoped to employees rather than bundling every OPVS tool,
because a single kitchen-sink server busts the tool cap most IDEs enforce and crowds out whatever
else you were doing.
One capability, three transports. The methods, the entitlements, and the brand pin are identical across all three; only the delivery differs.
Why the brand pin is not a parameter¶
Every non-public method resolves the brand from the credential, never from an argument. This is the security property the whole surface rests on, and it is the reason a prompt-injected agent cannot read a stranger's team: there is no argument for it to poison. A caller that names a brand in a header or a URL path does not thereby get that brand.
The alternative — trusting the agent to pass the right brand — fails the first time a model reads attacker-controlled text, which is roughly always.
Why hiring is fail-closed¶
Hiring spends money and consumes a plan seat, so it is gated on the brand's quota. The gate denies a token caller whenever no tariff rule resolves, rather than falling through to a permissive default.
That choice has a visible consequence today: with no service plans attached, hiring returns 403
for every brand. Reading the catalog, listing a team and reading a hire are unaffected. It is worth
being plain that this is the designed behaviour of an unfinished billing path, not a defect in the
agent surface. An agent that could loop against an inert cap is the failure this prevents, and a
capability that silently spends money because a lookup returned nothing is worse than one that
refuses.
What the split costs¶
Three channels mean three places a change has to land, and they can drift. The mitigation is that all three call the same seven methods against the same endpoints; none reimplements the logic. What differs is packaging, and packaging is cheap to keep in step.