Skip to content

fix(sdk): ship Pi's built-in tools in the default agent template (#5590) - #5597

Open
mmabrouk wants to merge 1 commit into
mainfrom
fix/pi-default-builtins
Open

fix(sdk): ship Pi's built-in tools in the default agent template (#5590)#5597
mmabrouk wants to merge 1 commit into
mainfrom
fix/pi-default-builtins

Conversation

@mmabrouk

Copy link
Copy Markdown
Member

Context

A saved agent could not run a shell command or write a file anywhere except the playground. Asked to do either, it answered that it had no shell or filesystem tool available.

Pi keeps seven tools inside the harness, and the run request names which of them to switch on. The runner treats a missing tools field as "use Pi's defaults" and an empty array as "grant nothing", and the Pi extension then deletes every non-granted tool from the model's list. The default agent template shipped an empty array, and the Python side always sends the field, so every saved agent said "grant nothing".

The playground hid this. Its build kit overlay adds read and bash back on every run, and nothing else does. So an agent worked while you built it and failed the moment a schedule ran it.

Changes

build_agent_v0_default() now ships Pi's own four defaults.

Before:

"tools": []

After:

"tools": [
  {"type": "builtin", "name": "read"},
  {"type": "builtin", "name": "bash"},
  {"type": "builtin", "name": "edit"},
  {"type": "builtin", "name": "write"}
]

The runner's rules are untouched. An empty list still means grant nothing, and the permission mode still gates bash, edit and write behind an approval. Having a tool is not the same as being allowed to use it.

Three supporting fixes ship with it:

The Claude harness warns only about built-ins outside that exact set. Built-ins are a Pi idea and Claude drops them, so without this every Claude run would log a warning about the four tools the template now always carries.

The built-in tool picker no longer tells you that clearing your selection leaves Pi's defaults on. It does the opposite.

The release gate seeds no longer hand-write the empty list, so the gate stops reporting green on the exact shape this change replaces.

Scope is deliberately new agents only. Agents saved before this keep their empty list and stay broken outside the playground. On one development deployment that is 66 of 73 Pi agents, so it is most of them. Repairing them is its own decision, filed as #5595 with the counting query.

Before merging

Do not deploy this to a shared deployment that still enables the local sandbox. The default sandbox is local, which runs on the runner host with no jail, and read never asks under the default permission mode. So a new agent could read host files unattended.

This adds no capability an author did not already have. Both the tool list and the sandbox are author-writable today, so anyone could already save the same agent and schedule it. What changes is what an unwitting author gets by default. Confirm AGENTA_RUNNER_ENABLED_SANDBOX_PROVIDERS excludes local before deploying, and remember that leaving it unset means local is enabled.

Tests

A crossing test now runs the real chain from the shipped default through the harness adapter to the /run body and asserts the four names arrive. Neither existing suite crossed that boundary, which is why both stayed green while every agent shipped with no tools.

The four names are pinned by a shared golden fixture that the Python and TypeScript suites both read, so the two languages cannot drift apart silently.

Runner 1308 passing, SDK 2330, API 1495, and 1427 across three web packages. Every error in the Python suites is an acceptance test asking for a live stack.

Verified on a running deployment: a fresh account's /inspect returns the four built-in entries as the default a new agent pre-fills with.

Reviewed by Codex at high effort before implementation, and by two independent reviewers after. Their findings and what was accepted or rejected are recorded in docs/design/agent-workflows/projects/default-agent-builtins/status.md.

What to QA

  • Create a new agent and open its tools. It lists read, bash, edit and write.
  • Ask it to write a file in the playground. It asks for approval first, then writes it.
  • Put that same agent on a schedule that writes a file. The run reaches the tool instead of reporting that it has none.
  • Regression: an agent you saved before this change behaves exactly as it did. It is not repaired and it is not made worse.
  • Regression: a Claude agent runs normally and its logs carry no new warning about built-in tools.

Closes #5590

@dosubot dosubot Bot added the size:XXL This PR changes 1000+ lines, ignoring generated files. label Jul 30, 2026
@vercel

vercel Bot commented Jul 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agenta-documentation Ready Ready Preview Jul 30, 2026 8:05pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Newly created agents now ship with Pi’s default built-in tools: read, bash, edit, and write.
    • The default agent configuration now consistently populates these tools across creation and invocation flows.
    • UI messaging updates clarify “No built-ins” when tools are cleared.
  • Bug Fixes

    • Prevented duplicate built-in tools when applying build overlays.
    • Improved Claude warning behavior to trigger only for non-default built-in sets.
  • Documentation

    • Updated agent configuration, tool semantics, schema defaults, and built-in documentation to reflect the new default tool set.

Walkthrough

The default Pi agent now grants read, bash, edit, and write built-ins across SDK, service, runner, and frontend paths. Shared parity fixtures, fallback behavior, harness warnings, gating tests, UI semantics, release seeds, and documentation were updated accordingly.

Changes

Default Pi built-in tool flow

Layer / File(s) Summary
Default grant contract and propagation
sdks/python/agenta/sdk/agents/..., services/oss/..., services/runner/..., api/oss/tests/...
A shared four-tool constant populates default configurations and is validated through catalog, fallback, parity, and wire-contract tests.
Harness warning and permission gating
sdks/python/agenta/sdk/agents/adapters/harnesses.py, services/runner/tests/..., docs/design/agent-workflows/interfaces/in-service/...
Claude warnings now use exact-set comparison, while runner tests cover gating under allow and allow_reads.
Frontend preservation and presentation
web/packages/agenta-entities/..., web/packages/agenta-entity-ui/..., web/packages/agenta-playground/...
Agent creation preserves built-ins, overlays avoid duplicates, and built-in labels and empty-selection messaging reflect explicit grant semantics.
Release-gate seed alignment
.agents/skills/agent-release-gate/resources/...
QA probe and product commit seed configurations include the four default built-ins.
Behavior and interface documentation
docs/design/agent-workflows/..., sdks/python/agenta/sdk/agents/adapters/agenta_builtins.py
Documentation describes default, omitted, and empty tools behavior, parity requirements, permission modes, and the scope for existing saved agents.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Sequence Diagram(s)

sequenceDiagram
  participant AgentTemplate
  participant ToolResolver
  participant PiHarness
  participant Runner
  AgentTemplate->>ToolResolver: Provide read, bash, edit, write
  ToolResolver->>PiHarness: Resolve builtin grant names
  PiHarness->>Runner: Send serialized tools list
  Runner->>Runner: Apply permission gating
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 39.13% which is insufficient. The required threshold is 60.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: shipping Pi's default built-in tools in the default agent template.
Description check ✅ Passed The description is detailed but directly aligned with the Pi default-tools fix and its supporting changes.
Linked Issues check ✅ Passed The changes address #5590 by giving new Pi agents read, bash, edit, and write in the default template and verifying it end to end.
Out of Scope Changes check ✅ Passed The extra docs, tests, and harness/UI tweaks all support the same default-builtins fix and do not appear unrelated.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/pi-default-builtins

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
services/oss/src/agent/config.py (1)

111-116: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Preserve default tools when agent.json omits the key.

tools is initialized with DEFAULT_TOOLS, but an existing agent.json without a tools field overwrites that value with []. This leaves partial templates with no Pi tools, while explicit "tools": [] should still retain the documented grant-nothing semantics. Add coverage for this case as well.

Proposed fix
         meta = json.loads(meta_path.read_text(encoding="utf-8"))
         model = meta.get("model") or DEFAULT_MODEL
-        tools = meta.get("tools", []) or []
+        if "tools" in meta:
+            tools = meta["tools"] or []
🧹 Nitpick comments (1)
web/packages/agenta-entities/tests/unit/create-ephemeral-app-from-template.test.ts (1)

58-60: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove any from the new workspace-package tests.

These casts can hide a broken agent-tools payload shape—the primary contract these tests are meant to protect.

  • web/packages/agenta-entities/tests/unit/create-ephemeral-app-from-template.test.ts#L58-L60: use a minimal unknown-based workflow/config shape and narrow before reading parameters.agent.
  • web/packages/agenta-playground/tests/unit/agentRequest.test.ts#L362-L372: type the request parameters/tools shape and use a narrow type guard for tool names.

Source: Coding guidelines


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 729092dc-5e31-4cba-af34-95f5b67f75c9

📥 Commits

Reviewing files that changed from the base of the PR and between 53aaf6f and 6144bf9.

📒 Files selected for processing (36)
  • .agents/skills/agent-release-gate/resources/qa_probe.py
  • .agents/skills/agent-release-gate/resources/qa_product.py
  • api/oss/tests/pytest/unit/resources/test_workflow_catalog.py
  • docs/design/agent-workflows/documentation/agent-configuration.md
  • docs/design/agent-workflows/documentation/tools.md
  • docs/design/agent-workflows/interfaces/README.md
  • docs/design/agent-workflows/interfaces/in-service/harness-adapters.md
  • docs/design/agent-workflows/interfaces/public-edge/agent-config-schema.md
  • docs/design/agent-workflows/projects/default-agent-builtins/README.md
  • docs/design/agent-workflows/projects/default-agent-builtins/context.md
  • docs/design/agent-workflows/projects/default-agent-builtins/design.md
  • docs/design/agent-workflows/projects/default-agent-builtins/open-questions.md
  • docs/design/agent-workflows/projects/default-agent-builtins/plan.md
  • docs/design/agent-workflows/projects/default-agent-builtins/research.md
  • docs/design/agent-workflows/projects/default-agent-builtins/status.md
  • docs/design/agent-workflows/projects/default-agent-builtins/testing.md
  • sdks/python/agenta/sdk/agents/adapters/agenta_builtins.py
  • sdks/python/agenta/sdk/agents/adapters/harnesses.py
  • sdks/python/agenta/sdk/agents/pi_builtins.py
  • sdks/python/agenta/sdk/utils/types.py
  • sdks/python/oss/tests/pytest/unit/agents/golden/pi_default_active_builtins.json
  • sdks/python/oss/tests/pytest/unit/agents/test_harness_adapters.py
  • sdks/python/oss/tests/pytest/unit/agents/test_pi_builtins_parity.py
  • sdks/python/oss/tests/pytest/unit/agents/test_wire_contract.py
  • services/oss/src/agent/config.py
  • services/oss/tests/pytest/unit/agent/test_config_template_fallback.py
  • services/oss/tests/pytest/unit/agent/test_default_agent_template.py
  • services/runner/config/agent.json
  • services/runner/src/engines/sandbox_agent/run-plan.ts
  • services/runner/tests/unit/pi-default-builtins-parity.test.ts
  • services/runner/tests/unit/sandbox-agent-run-plan.test.ts
  • web/packages/agenta-entities/tests/unit/create-ephemeral-app-from-template.test.ts
  • web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/PiSettingsControl.tsx
  • web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/agentTemplate/itemDescriptors.tsx
  • web/packages/agenta-entity-ui/tests/unit/itemDescriptors.test.ts
  • web/packages/agenta-playground/tests/unit/agentRequest.test.ts

| [`/inspect`](public-edge/workflow-inspect.md) | public | `agent/schemas.py`, `agent/app.py` (builtin-URI binding), `models/workflows.py`, `decorators/routing.py` | stable | `unit/agents/test_dtos_agent_config.py`, `unit/agent/test_builtin_uri_binding.py` |
| [`/messages`](public-edge/agent-messages.md) | public | `adapters/vercel/{routing,messages,stream}.py`, `agentRequest.ts` | evolving (create-or-resume not observable until storage lands) | `utils/test_messages_endpoint.py`, `unit/agents/test_ui_messages.py` |
| [Agent config schema](public-edge/agent-config-schema.md) | public | `agent/schemas.py`, `sdk/utils/types.py`, `agents/dtos.py` (`HARNESS_IDENTITIES`) | stable | `unit/agents/test_dtos_agent_config.py`, `unit/agents/test_harness_identity.py` |
| [Agent config schema](public-edge/agent-config-schema.md) | public | `agent/schemas.py`, `sdk/utils/types.py`, `agents/dtos.py` (`HARNESS_IDENTITIES`), `sdk/agents/pi_builtins.py` (`PI_DEFAULT_ACTIVE_BUILTINS`) | stable | `unit/agents/test_dtos_agent_config.py`, `unit/agents/test_harness_identity.py`, `unit/agents/test_pi_builtins_parity.py` + `golden/pi_default_active_builtins.json`, `services/oss unit/agent/test_default_agent_template.py` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix the malformed test path.

services/oss unit/agent/test_default_agent_template.py is not the repository path; it should be services/oss/tests/pytest/unit/agent/test_default_agent_template.py, otherwise this interface inventory points reviewers to a nonexistent location.

Proposed fix
-| ... | `unit/agents/test_pi_builtins_parity.py` + `golden/pi_default_active_builtins.json`, `services/oss unit/agent/test_default_agent_template.py` |
+| ... | `unit/agents/test_pi_builtins_parity.py` + `golden/pi_default_active_builtins.json`, `services/oss/tests/pytest/unit/agent/test_default_agent_template.py` |
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
| [Agent config schema](public-edge/agent-config-schema.md) | public | `agent/schemas.py`, `sdk/utils/types.py`, `agents/dtos.py` (`HARNESS_IDENTITIES`), `sdk/agents/pi_builtins.py` (`PI_DEFAULT_ACTIVE_BUILTINS`) | stable | `unit/agents/test_dtos_agent_config.py`, `unit/agents/test_harness_identity.py`, `unit/agents/test_pi_builtins_parity.py` + `golden/pi_default_active_builtins.json`, `services/oss unit/agent/test_default_agent_template.py` |
| [Agent config schema](public-edge/agent-config-schema.md) | public | `agent/schemas.py`, `sdk/utils/types.py`, `agents/dtos.py` (`HARNESS_IDENTITIES`), `sdk/agents/pi_builtins.py` (`PI_DEFAULT_ACTIVE_BUILTINS`) | stable | `unit/agents/test_dtos_agent_config.py`, `unit/agents/test_harness_identity.py`, `unit/agents/test_pi_builtins_parity.py` + `golden/pi_default_active_builtins.json`, `services/oss/tests/pytest/unit/agent/test_default_agent_template.py` |

Comment thread docs/design/agent-workflows/projects/default-agent-builtins/plan.md
Comment on lines +35 to +37
- **Agent template**: the saved agent configuration at `parameters.agent` of a workflow revision.
It holds instructions, model, tools, MCP servers, skills, and the execution selectors
(`harness`, `runner`, `sandbox`).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Reconcile the execution-selector field list.

This says the saved template contains harness, runner, and sandbox, but docs/design/agent-workflows/interfaces/public-edge/agent-config-schema.md documents harness, sandbox, and permissions as the run-selection fields. Replace runner with permissions or explicitly define runner if it is intended to be persisted.

Comment on lines +181 to +184
`permission` is dropped — builtins are granted by selection, not gated.) A new agent starts
with Pi's four defaults (`read`, `bash`, `edit`, `write`), as shown above. Keep them unless the
user asks you to drop one: an empty `tools` list grants NO built-ins, so an agent that ships
with `[]` cannot read or write a file at all.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Clarify that runner-level permission gating still applies.

The per-tool permission field may be dropped, but built-ins are still gated by the runner permission mode: under allow_reads, read runs without approval while bash, edit, and write require approval. Replace “not gated” with wording that distinguishes selection/granting from execution permission.

A saved agent shipped `tools: []`, which the runner reads as "grant Pi no
built-in tools", so the agent had no read, bash, edit or write anywhere except
the playground. The playground hid it: its build kit overlay adds read and bash
back on every run, and nothing else does.

The default template now ships Pi's own four defaults as typed builtin entries.
The runner's grant semantics are untouched, and the permission mode still gates
bash, edit and write behind an approval.

Also: the Claude harness only warns about built-ins that differ from that exact
set, the built-in picker no longer claims an empty selection leaves Pi's
defaults on, and a built-in row shows its own name.

Closes #5590
@github-actions

Copy link
Copy Markdown
Contributor

Railway Preview Environment

Preview URL https://gateway-production-cc25.up.railway.app/w
Project agenta-oss-pr-5597
Image tag pr-5597-8f0b35f
Status Deployed
Railway logs Open logs
Workflow logs View workflow run
Updated at 2026-07-30T20:10:22.126Z

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (2)
web/packages/agenta-playground/tests/unit/agentRequest.test.ts (1)

362-372: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Avoid introducing any in this workspace-package test.

Use the existing request type or narrow unknown values before accessing parameters.agent.tools; the new as any and (tool: any) suppress schema regressions that this test should catch.

As per coding guidelines, workspace packages should avoid any.

Source: Coding guidelines

web/packages/agenta-entities/tests/unit/create-ephemeral-app-from-template.test.ts (1)

58-60: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Keep the test helper type-safe.

Record<string, any> and as any suppress TypeScript checks, while optional chaining can still return undefined. Define the small agent-config shape needed by these assertions and fail explicitly when the entity is missing.

Proposed fix
-function readAgentConfig(localId: string): Record<string, any> {
-    const entity = getDefaultStore().get(workflowLocalServerDataAtomFamily(localId)) as any
-    return entity?.data?.parameters?.agent
+type AgentConfig = {
+    harness?: {kind?: string}
+    llm?: {model?: string; provider?: string}
+    tools?: Array<{type: "builtin"; name: string}>
+}
+
+function readAgentConfig(localId: string): AgentConfig {
+    const entity = getDefaultStore().get(workflowLocalServerDataAtomFamily(localId)) as
+        | {data?: {parameters?: {agent?: AgentConfig}}}
+        | undefined
+    const agent = entity?.data?.parameters?.agent
+    if (!agent) throw new Error(`Agent workflow ${localId} was not created`)
+    return agent
}

As per coding guidelines, workspace package TypeScript code should avoid any.

Source: Coding guidelines


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a01f2878-bfdb-495e-a417-7f955d1cf5e8

📥 Commits

Reviewing files that changed from the base of the PR and between 6144bf9 and 4c6fd34.

📒 Files selected for processing (36)
  • .agents/skills/agent-release-gate/resources/qa_probe.py
  • .agents/skills/agent-release-gate/resources/qa_product.py
  • api/oss/tests/pytest/unit/resources/test_workflow_catalog.py
  • docs/design/agent-workflows/documentation/agent-configuration.md
  • docs/design/agent-workflows/documentation/tools.md
  • docs/design/agent-workflows/interfaces/README.md
  • docs/design/agent-workflows/interfaces/in-service/harness-adapters.md
  • docs/design/agent-workflows/interfaces/public-edge/agent-config-schema.md
  • docs/design/agent-workflows/projects/default-agent-builtins/README.md
  • docs/design/agent-workflows/projects/default-agent-builtins/context.md
  • docs/design/agent-workflows/projects/default-agent-builtins/design.md
  • docs/design/agent-workflows/projects/default-agent-builtins/open-questions.md
  • docs/design/agent-workflows/projects/default-agent-builtins/plan.md
  • docs/design/agent-workflows/projects/default-agent-builtins/research.md
  • docs/design/agent-workflows/projects/default-agent-builtins/status.md
  • docs/design/agent-workflows/projects/default-agent-builtins/testing.md
  • sdks/python/agenta/sdk/agents/adapters/agenta_builtins.py
  • sdks/python/agenta/sdk/agents/adapters/harnesses.py
  • sdks/python/agenta/sdk/agents/pi_builtins.py
  • sdks/python/agenta/sdk/utils/types.py
  • sdks/python/oss/tests/pytest/unit/agents/golden/pi_default_active_builtins.json
  • sdks/python/oss/tests/pytest/unit/agents/test_harness_adapters.py
  • sdks/python/oss/tests/pytest/unit/agents/test_pi_builtins_parity.py
  • sdks/python/oss/tests/pytest/unit/agents/test_wire_contract.py
  • services/oss/src/agent/config.py
  • services/oss/tests/pytest/unit/agent/test_config_template_fallback.py
  • services/oss/tests/pytest/unit/agent/test_default_agent_template.py
  • services/runner/config/agent.json
  • services/runner/src/engines/sandbox_agent/run-plan.ts
  • services/runner/tests/unit/pi-default-builtins-parity.test.ts
  • services/runner/tests/unit/sandbox-agent-run-plan.test.ts
  • web/packages/agenta-entities/tests/unit/create-ephemeral-app-from-template.test.ts
  • web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/PiSettingsControl.tsx
  • web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/agentTemplate/itemDescriptors.tsx
  • web/packages/agenta-entity-ui/tests/unit/itemDescriptors.test.ts
  • web/packages/agenta-playground/tests/unit/agentRequest.test.ts
🚧 Files skipped from review as they are similar to previous changes (6)
  • docs/design/agent-workflows/interfaces/README.md
  • docs/design/agent-workflows/projects/default-agent-builtins/context.md
  • docs/design/agent-workflows/documentation/agent-configuration.md
  • web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/PiSettingsControl.tsx
  • docs/design/agent-workflows/interfaces/public-edge/agent-config-schema.md
  • sdks/python/agenta/sdk/agents/adapters/agenta_builtins.py

Comment on lines +82 to +90
# Pi's default active built-ins, matching the shipped default agent template. An empty
# list means "grant nothing" to the runner, so seeding `[]` would gate the release on a
# configuration no real agent uses (issue #5590).
"tools": [
{"type": "builtin", "name": "read"},
{"type": "builtin", "name": "bash"},
{"type": "builtin", "name": "edit"},
{"type": "builtin", "name": "write"},
],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n -C 4 '\bagent_template\s*\(' .agents/skills/agent-release-gate
rg -n -i -C 4 'claude|harness' .agents/skills/agent-release-gate

Repository: Agenta-AI/agenta

Length of output: 42411


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== qa_probe.py relevant ranges =="
sed -n '60,135p' .agents/skills/agent-release-gate/resources/qa_probe.py | cat -n

echo
echo "== qa_product.py relevant ranges =="
sed -n '700,780p' .agents/skills/agent-release-gate/resources/qa_product.py | cat -n
sed -n '230,270p' .agents/skills/agent-release-gate/resources/qa_product.py | cat -n

echo
echo "== definitions/calls focused =="
rg -n -C 3 'def j5_commit|j5_commit|agent_template\(harness|tools=.*Pi|Pi.*tools|read_builtin|read_tool|Terminal|Bash|capabilities' .agents/skills/agent-release-gate/resources/qa_product.py .agents/skills/agent-release-gate/resources/qa_probe.py

echo
echo "== deterministic probe for tool default shape across harnesses =="
python3 - <<'PY'
import re, pathlib
qa_product = pathlib.Path(".agents/skills/agent-release-gate/resources/qa_product.py").read_text()
qa_probe = pathlib.Path(".agents/skills/agent-release-gate/resources/qa_probe.py").read_text()

def find_seed_comment_region(text, needle, start=0, end=None):
    idx = text.find(needle, start, end)
    if idx == -1:
        return None
    before = text.rfind("\n", 0, idx)
    after = text.find("\n", idx)
    # grab from before comment up to next def/class/main/import or end
    next_block = re.search(r"\n\ndef |\n\nclass |\nif __name__", text, idx + 1)
    boundary = next_block.start() if next_block else len(text)
    return text[before:boundary]

for name, txt, needle in [
    ("qa_probe.py", qa_probe, "Pi's default active built-ins"),
    ("qa_product.py", qa_product, "Pi's default active built-ins"),
]:
    block = find_seed_comment_region(txt, needle)
    print(f"--- {name} around seed comment ---")
    print(block)
    print(f"contains cell[\"harness\"] in seed block? {'cell[\"harness\"]' in block}")
    print(f"contains harness == in seed block? {'harness' in block}")
PY

Repository: Agenta-AI/agenta

Length of output: 13909


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== j5_commit callers and config construction =="
rg -n -C 8 'template\(|run\.commit|parameters|j5_commit|cell\["harness"\]|harness.*==|startswith' .agents/skills/agent-release-gate/resources/qa_product.py

echo
echo "== call graph for j5_commit and template direct usages =="
python3 - <<'PY'
from pathlib import Path
p = Path(".agents/skills/agent-release-gate/resources/qa_product.py").read_text()
for needle in ["j5_commit(", "'j5_commit':", "template("]:
    print(f"-- {needle} --")
    for i, line in enumerate(p.splitlines(), 1):
        if needle in line:
            print(f"{i}: {line}")
PY

Repository: Agenta-AI/agenta

Length of output: 13009


Gate Pi tool defaults to Pi harnesses.

The probe seed is unconditional, and j5_commit() builds the same Pi default tool list for any cell["harness"], including Claude cells. Wrap those defaults behind harness.startswith("pi") / cell["harness"].startswith("pi"), or pass non-Pi defaults for Claude.

📍 Affects 2 files
  • .agents/skills/agent-release-gate/resources/qa_probe.py#L82-L90 (this comment)
  • .agents/skills/agent-release-gate/resources/qa_product.py#L752-L760

Comment on lines +58 to +77
## Should `read` be approval-free on the local sandbox?

**Needs a decision before this ships to a shared deployment.**

`read` is classified read-only (`permission-plan.ts:40`) and `allow_reads` runs it without asking.
On the shipped default sandbox `local`, that is an approval-free read of any file the runner
process can open: the run executes on the runner host (`provider.ts:148`), Pi's `read` accepts
absolute paths and applies no cwd jail, and `AGENTA_RUNNER_ENABLED_SANDBOX_PROVIDERS` defaults to
`["local"]` when unset. The full trace is in
[design.md](design.md#what-read-can-reach-on-the-local-sandbox).

The capability exists today through the playground overlay. What this change adds is the
unattended, non-playground version of it. Three responses are available and they are not
equivalent: stop enabling `local` by default, confine built-in filesystem operations to the run
cwd in the runner, or reclassify `read` so it also asks. The first is deployment policy, the second
is runner work, the third would make the default agent ask before every file read and is probably
too blunt.

This is not a reason to drop `read` from the default template. It is a reason not to ship the
default template into a shared deployment that still enables `local`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Resolve the unconfined local sandbox risk before shipping.

The new default grants read, and allow_reads permits it without approval. With local enabled, an unattended Pi run can read absolute paths on the runner host because no cwd jail is applied. Exclude local from shared deployments or enforce filesystem confinement before releasing this default.

Comment on lines +129 to +144
## Do the four built-in names now collide with an author's own tool?

**Known consequence of this change. Not fixed here, and worth watching.**

`read`, `bash`, `edit` and `write` are now occupied names for every agent created from the default
template. Built-in names and resolved tool specs share one namespace: `_validate_unique_names`
(`sdks/python/agenta/sdk/agents/tools/resolver.py:84`) walks `[*builtin_names, *tool_specs]` and
raises `DuplicateToolNameError` on the first repeat, which fails the whole run. An author-defined
client tool, gateway tool, or workflow tool called `write` was legal before this change and now
aborts the run of any agent that still carries the shipped built-ins.

The blast radius is small (the names are short and generic, but an author who wanted one has to
have picked exactly it) and the failure is loud rather than silent, which is why the behavior is
left alone. The options, if it does bite: namespace built-ins on the wire so the two sets cannot
collide, let an author tool of the same name shadow the built-in rather than fail, or keep failing
and say so in the picker before the run.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Prevent built-in/custom-tool name collisions from aborting runs.

The new default occupies read, bash, edit, and write, while the resolver rejects duplicate names. A previously valid custom tool named write can therefore make a newly created agent fail at runtime. Add save-time validation, namespacing, or an explicit precedence rule before shipping.

Comment on lines +62 to +65
The read-only table at `services/runner/src/permission-plan.ts:40` marks `read`, `grep`, `find`,
and `ls` read-only, and `bash`, `edit`, `write` not read-only. Under the shipped default
permission mode `allow_reads` (`sdks/python/agenta/sdk/utils/types.py:1072`), the read-only four
run without asking and the other three raise an approval.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Clarify that allow_reads only permits granted read-only tools.

The default grant contains read, not grep, find, or ls; those tools are classified as read-only but are inactive unless granted. Reword this to avoid implying that all four execute by default.

Comment on lines +3 to +6
**State: implemented, uncommitted. All four pieces are in the working tree; no branch and no pull
request yet.**

Last updated 2026-07-30, after implementation.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Update the implementation status before merging.

This still says the work is uncommitted and has no branch or pull request, which is stale in the current PR. Replace it with the actual implementation/PR state and update the timestamp as needed.

Comment on lines +65 to +73
```python
def test_published_default_grants_pi_default_builtins():
"""A new agent must be able to read, run shell commands, and edit and write files wherever it
runs, not only in the playground (issue #5590). The runner reads an empty tools list as
"grant nothing"."""
expected = [{"type": "builtin", "name": name} for name in PI_DEFAULT_BUILTIN_NAMES]
assert _inspect_agent_default()["tools"] == expected
assert _builtin_agent_default()["tools"] == expected
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use the actual constant name in the test example.

PI_DEFAULT_BUILTIN_NAMES does not exist; the shipped symbol is PI_DEFAULT_ACTIVE_BUILTINS. Update the snippet so readers do not copy a failing import or assertion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

(bug) Pi agents run with no read, bash, edit or write tools outside the playground

1 participant