Give agents hands: workspace read/list/exec tools so engineers build instead of describing
Every "engineering" deliverable the company ever produced was a markdown skeleton, because documentation was the ceiling of the toolset: write_deliverable and create_document were the only artifact tools. An engineer could not see the files that exist, read a line of code, or run a single command — and create_task hardcoded requires_filesystem to false, so the entire approval-gated read_write mount plumbing was dead code. New workspace capability (agent-workspace-tools.ts): - list_files / read_file: explore the bound workspace, traversal-guarded by the same resolveWorkspacePath used for writes, size- and count-capped. - run_command: real shell execution with the workspace as cwd, 120s timeout, 16k output cap. Gated on the task's approved filesystem grant — the same requires_filesystem flag that flips the mount to read_write and routes the task through operator approval (auto-approved only in AI-CEO mode, which is that mode's explicit contract). - create_task now takes requires_filesystem, so the CEO and officers can delegate engineering work that is allowed to change code and run tests. - Prompts brief every agent on the tools, and filesystem tasks state the bar directly: real output is code that builds and tests that pass — a document describing the work does not close an engineering task. Tests: tool registry, dependency-folder-skipping listing, traversal refusal, the run_command access gate plus exit-code reporting, and the create_task approval path for filesystem work.
This commit is contained in:
1 parent
9c85b5ee3c
commit
291816aa06
8 files changed
+285
-8
No files matched your search
@@ -22,7 +22,8 @@ export interface AgentToolContext {
|
||||
agent: { id: string; modelProviderId: string | null; modelId: string | null };
|
||||
taskProjectId: string | null;
|
||||
taskGoalId: string | null;
|
||||
workspace: { id: string; localPath: string } | null;
|
||||
/** writeAccess mirrors the task's approved filesystem grant (read_write mount) and gates run_command. */
|
||||
workspace: { id: string; localPath: string; writeAccess: boolean } | null;
|
||||
}
|
||||
|
||||
export interface AgentToolDeps {
|
||||
@@ -71,6 +72,10 @@ export const AGENT_TOOLS: ToolDefinition[] = [
|
||||
description: { type: "string" },
|
||||
assignee_agent_name: { type: "string", description: "Name of the agent to assign, if any." },
|
||||
risk: { type: "string", enum: ["low", "medium", "high"] },
|
||||
requires_filesystem: {
|
||||
type: "boolean",
|
||||
description: "Set true for engineering work that must change code or run commands (build, test) in the workspace. The assignee then gets run_command; the operator approves such tasks before they execute.",
|
||||
},
|
||||
},
|
||||
required: ["title", "description"],
|
||||
},
|
||||
@@ -307,7 +312,7 @@ function createTask(deps: AgentToolDeps, ctx: AgentToolContext, args: JsonRecord
|
||||
goalId: ctx.taskGoalId,
|
||||
workspaceId: ctx.workspace?.id ?? null,
|
||||
priority: TASK_PRIORITY.NORMAL,
|
||||
requiresFilesystem: false,
|
||||
requiresFilesystem: args.requires_filesystem === true,
|
||||
});
|
||||
const assignmentThread = options.announceTaskAssignments !== false && assignee && assignee.id !== ctx.agent.id
|
||||
? postAssignmentMessage(deps, ctx, { taskId, title, description, assignee })
|
||||
|
||||
Reference in new issue
Block a user