Ch7. Tools, Approval, Connections
Design Eve authored tools, human approval, MCP/OpenAPI connections, and OAuth boundaries as enterprise security surfaces.
핵심 요약
- Authored tool
executeruns in the app runtime, not in the sandbox, so it is a privileged surface. toModelOutput,needsApproval, and auth scope control data exposure and risky actions.- MCP/OpenAPI connections expand capabilities quickly, but require allow-lists, approval, and OAuth boundaries.
Tools are typed actions the model can request. The most important operational fact is that authored tool execute runs in the app runtime. If it can access secrets or internal APIs, treat it as privileged code.
Tool Structure
import { defineTool } from "eve/tools";
import { z } from "zod";
export default defineTool({
description: "Return mock weather data for a city.",
inputSchema: z.object({ city: z.string().min(1) }),
async execute({ city }) {
return { city, condition: "Sunny", temperatureF: 72 };
},
});Standards:
descriptionis model-facing routing textinputSchemais a control surfaceexecutemust tolerate replay and retries- returned data may enter history and telemetry, so minimize it
Minimize Model-visible Output
Use toModelOutput when hooks/channels need rich output but the model should see only a summary.
toModelOutput(output) {
return {
type: "text",
value: `Report ${output.id}: risk ${output.riskLevel}.`,
};
}This prevents CRM rows, audit payloads, pricing tables, and PII from being copied into later model context.
Approval Policy
| Helper | Behavior |
|---|---|
never() | no approval; omission has the same effect |
once() | approve first execution per session |
always() | approve every execution |
| predicate | decide from tool input |
import { defineTool } from "eve/tools";
import { always } from "eve/tools/approval";
import { z } from "zod";
export default defineTool({
description: "Refund a customer charge.",
inputSchema: z.object({
chargeId: z.string(),
amount: z.number().positive(),
}),
needsApproval: always(),
async execute(input) {
return refundCharge(input);
},
});Input-based Approval
needsApproval: ({ toolInput }) => {
const amount = Number(toolInput?.amount ?? 0);
return amount > 1000;
}Keep business policy in pure functions under agent/lib/ and unit test it. Do not hide large policy logic inside tool definitions.
HITL Is Durable Parking
When approval is required, Eve emits input.requested and parks the session in session.waiting. The process is not held open. The session resumes when the answer arrives.
Connections
Connections expose external MCP or OpenAPI tools that you do not author.
| Connection | Helper | Model-visible tool name |
|---|---|---|
| MCP | defineMcpClientConnection | connection__<connection>__<tool> |
| OpenAPI | defineOpenAPIConnection | connection__<connection>__<operationId> |
The model discovers them through connection__search and calls qualified names.
import { defineMcpClientConnection } from "eve/connections";
import { once } from "eve/tools/approval";
export default defineMcpClientConnection({
url: "https://mcp.linear.app/sse",
description: "Linear workspace: issues, projects, cycles, and comments.",
auth: {
getToken: async () => ({ token: process.env.LINEAR_API_TOKEN! }),
},
tools: { allow: ["search_issues", "get_issue"] },
approval: once(),
});Tokens Stay Out Of The Model
Connection tokens are resolved in the app runtime and injected into outbound requests. They do not become model context. This is a major safety property, but scope still matters.
| Risk | Response |
|---|---|
| shared app token reaches all tenant data | use user or tenant-scoped token |
| too many MCP tools exposed | use allow-list |
| write operation has no approval | split tools or use approval: always() |
| token revoked mid-call | map provider 401 to ctx.requireAuth() |
Tool Auth vs Connection Auth vs Route Auth
| Surface | Purpose |
|---|---|
| route auth | who may call Eve routes |
| tool auth | one custom tool needs OAuth |
| connection auth | an external MCP/OpenAPI server needs credentials |
Route auth does not automatically make tool or connection scopes safe.
ask_question vs Approval
| Purpose | Eve feature |
|---|---|
| permission to execute | needsApproval |
| missing information | built-in ask_question |
| OAuth consent | tool or connection auth |
All use the same durable input.requested pause protocol, but their intent is different.
Tool Design Checklist
| Item | Standard |
|---|---|
| input schema | strict validation and limits |
| output minimization | model sees only what it needs |
| idempotency | external writes use key or ledger |
| approval | irreversible/sensitive actions gated |
| auth | token scope and principal type explicit |
| observability | action.result hook can audit |
| eval | calledTool/noFailedActions/output checks |
Ch6. Context, Skills, Dynamic Capabilities
Design context, skills, dynamic tools, dynamic instructions, and dynamic skills for high-quality Eve agents.
Ch8. Sandbox Secure Runtime
Turn Eve sandbox trust boundaries, backends, network policy, credential brokering, and workspace lifecycle into operating standards.