## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work.
> - The native runner exposes tools for company tasks.
> - API search and call tools cover operations without a dedicated tool.
> - The current default hides these tools unless an operator sets an
environment variable.
> - This pull request enables the tools when that variable is absent.
> - Operators can still disable the tools or restrict them to selected
companies.
## Linked Issues or Issue Description
Refs #13003, which added the guarded API tools.
**What happened?**
The native runner does not advertise `search_api` or `call_api` with the
default server configuration.
**Expected behavior**
The tools are available without a special environment variable. Existing
authorization checks still apply.
**Steps to reproduce**
Remove `PAPERCLIP_RUNNER_API_TOOLS_ENABLED` and
`PAPERCLIP_RUNNER_API_TOOLS_COMPANY_IDS`. Create a normal runner
authority. Inspect its tool definitions.
**Paperclip version or commit**
a6c4e7a.
## What Changed
- Enable API tools when the server flag is absent.
- Keep explicit disable, invalid-value rejection, company restrictions,
and binding restrictions.
- Test default tool definitions and run HTTP integration tests without
the enabling flag.
- Update operator and hiring documentation. The existing shared gate
also controls `hire_agent`.
- Use the same policy in the E2E evidence summary so an unset flag is
not reported as disabled.
- Isolate default-availability tests from operator environment
variables.
## Verification
- Red test: two new rollout policy assertions failed before the fix.
- Focused policy, authority, and HTTP tests: 3 files passed; 41 tests
passed, 2 skipped. The two runnerd transport cases require a Rust-built
binary absent from this workspace.
- Command: `pnpm exec vitest run
server/src/services/native-runtime/runner-api-rollout.test.ts
server/src/services/native-runtime/paperclip-runner-tool-authority.test.ts
server/src/services/native-runtime/runner-api.integration.test.ts`.
- Attempted `pnpm -r typecheck`: blocked by missing `cargo` in this
workspace.
- Attempted `pnpm build`: terminated at the 4 GiB memory limit.
- Attempted `pnpm test:run`: stopped after memory pressure to run
focused tests alone.
- Repeated the 41 passing focused tests with an inherited disabled flag
and a foreign-company restriction; test isolation passed.
- `pnpm test:e2e:runner:unit`: 44 files and 543 tests passed.
- `pnpm test:e2e:runner:typecheck` exceeded the workspace memory limit,
including a retry with bounded Go memory settings.
- CI results will be recorded before handoff.
## Risks
- More native runs can discover API tools and the existing `hire_agent`
tool by default.
- The change does not remove company, run, mode, credential, lifecycle,
or approval checks.
- Explicit operator restrictions still take precedence. No database
migration is required.
## Model Used
OpenAI Codex agent. The runtime does not expose the exact model ID or
context-window size. Used reasoning, repository tools, shell execution,
and tests.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
AI connections through hiring
Paid, opt-in acceptance against a separate loopback local_trusted instance. Each
scenario creates its own company and accounts. It never edits an existing company.
Do not start the server with provider API keys: ambient credentials could mask
missing managed-connection bindings.
Start from a fresh worktree with dependencies installed:
pnpm exec tsx cli/src/index.ts test-drive --data-dir /tmp/paperclip-hiring-qa --no-browser
Use the URL printed at startup. Test-drive may choose another available port when
restarted. In a separate shell, export ANTHROPIC_API_KEY and OPENAI_API_KEY, then:
HIRING_AI_LIVE=1 HIRING_AI_TEST_URL=http://127.0.0.1:3100 \
pnpm exec playwright test --config tests/hiring-ai-connections/playwright.config.ts --grep 'local:'
For both Claude and Codex, the browser creates a task instructing the real parent to hire one agent of each provider and create a self-assigned subtask. The server's activity log must attribute both hires to the parent agent. The test verifies the subtask and a task assigned to the same-provider hire finish under the original managed account. It then assigns work to the other provider, checks the pending AI connection card, connects with an API key in the card, and verifies the task resumes and finishes without sending another message or clicking retry. Completion comments must be authored by the assigned agent; account and responsible-user attribution are checked on the successful runs.
Provider calls use real credentials and incur usage. The fixture uses Claude Sonnet 4.6 and Codex GPT-5.4 through their CLI adapters. Provider subscription sign-in is not automated by this live suite. Integration tests cover subscription inheritance, credential serialization, and automatic retry after the parent's lease is released.
The newer native runner enables its managed API and hiring tools by default. No enabling environment variable is required. Operator restrictions still apply; see Runner API tools. For native coverage, use:
HIRING_AI_LIVE=1 HIRING_AI_RUNNER=native HIRING_AI_TEST_URL=http://127.0.0.1:3100 \
pnpm exec playwright test --config tests/hiring-ai-connections/playwright.config.ts --grep 'local: native: Codex'
This uses native Codex and native ACPX/Claude. It verifies native run persistence,
managed API hiring, native create_task delegation, and paperclip_finish
completion. Set HIRING_AI_ENVIRONMENT=daytona to exercise the same native path
remotely. The default remains legacy CLI adapters; it also asserts that successful
runs stayed on the legacy path. A single native parent scenario exercises both
native worker providers without repeating the full matrix.
Daytona
Build the plugin and provide DAYTONA_API_KEY plus an immutable, qualified runner
image digest. See tests/runner-e2e/README.md for the image publication workflow.
pnpm -C packages/plugins/sandbox-providers/daytona build
HIRING_AI_LIVE=1 HIRING_AI_ENVIRONMENT=daytona \
HIRING_AI_TEST_URL=http://127.0.0.1:3100 \
HIRING_AI_DAYTONA_IMAGE=ghcr.io/paperclipai/paperclip-daytona-runner@sha256:YOUR_DIGEST \
pnpm exec playwright test --config tests/hiring-ai-connections/playwright.config.ts --grep 'daytona:'
The same tests install the plugin only in the disposable instance, create a Daytona environment, and assign it to the parent and both hires. Successful runs must report that environment. The finalizer cancels remaining active runs in the test company and deletes the environment and its leases. Task history and encrypted connections remain in the disposable data directory for inspection.
Native Daytona also requires the controller's remote runner binary and provider pack. On a Mac, use the Linux artifacts from the same qualified image, not the local runner binary. The pack must match this checkout's provider pins and profile digests; a newer image is not automatically compatible. Extract into an empty destination directory without starting the container:
mkdir -p /tmp/hiring-native-artifacts
hiring_image_container=$(docker create "$HIRING_AI_DAYTONA_IMAGE" /bin/true)
docker cp "$hiring_image_container:/opt/paperclip-runner/provider-pack" /tmp/hiring-native-artifacts/provider-pack
docker cp "$hiring_image_container:/usr/local/bin/paperclip-runnerd" /tmp/hiring-native-artifacts/paperclip-runnerd
docker rm "$hiring_image_container"
Add these settings to the disposable instance's instances/default/.env, alongside
the native API-tools flag, and restart test-drive:
PAPERCLIP_RUNNER_REMOTE_PROVIDER_PACK_PATH=/tmp/hiring-native-artifacts/provider-pack
PAPERCLIP_RUNNER_REMOTE_BINARY_PATH=/tmp/hiring-native-artifacts/paperclip-runnerd
Run the Daytona command with HIRING_AI_RUNNER=native and
--grep 'daytona: native: Claude' for one representative native remote scenario.
If no matching image is available, use the runnerd-build and
provider-pack-build Docker targets from this checkout, following the runner E2E
workflow's lockfile resolution. Configure both resulting Linux artifacts together;
native startup can stage them over a different image's preinstalled artifacts.
Mixing a newer runner binary with an older provider pack can fail the sidecar
handshake even when the individual provider version pins match.
Regression and Storybook checks
pnpm exec vitest run server/src/__tests__/agent-hire-ai-connections.test.ts \
server/src/services/legacy-execution-recovery.test.ts \
server/src/services/execution-recovery-attempt.test.ts \
server/src/services/native-runtime/runner-api.integration.test.ts \
ui/src/features/connections/ConnectionIntentInteractionBody.test.tsx
pnpm --filter @paperclipai/ui exec storybook dev -p 6010 -c storybook/.storybook --ci --no-open
HIRING_AI_STORYBOOK_URL=http://127.0.0.1:6010 \
pnpm exec playwright test --config tests/hiring-ai-connections/playwright.config.ts --grep storybook
The Storybook checks use the production card and credential components with fixture API responses. They cover both providers, API/subscription choice, a narrow viewport, completion, cancellation, and invalid credentials. They do not contact providers.
The Daytona plugin's file-sync.test.ts also exercises real GNU tar extraction of
interleaved read-only skill directories. It runs on Linux and on macOS with
gnu-tar installed. This guards the macOS-to-Daytona staging failure where directory
permissions were restored before all skill files arrived, while asserting that the
finished directory and files retain their read-only modes.
Screenshots and redacted account/run attribution are written under test-results/.
Traces, videos, and automatic failure screenshots are disabled because credential
fields are involved. Each Playwright invocation clears its output directory; use
--output to preserve separate local, Daytona, and Storybook evidence. Keep credentials
out of issue descriptions, console output, command-line arguments, and attachments.