# Tools, Network, and Secrets

Learn the difference between workspace tools, pack-defined tools, and engine primitives, and how network and secret handling are constrained.

Source: https://agentclash.dev/docs/concepts/tools-network-and-secrets
Markdown export: https://agentclash.dev/docs-md/concepts/tools-network-and-secrets

AgentClash has more than one “tool” layer. If you do not separate them mentally, the rest of the runtime model gets confusing fast.

## There are three different layers to know

### 1. Workspace tool resources

The workspace API already exposes first-class `tools` resources with fields like:

- `name`
- `tool_kind`
- `capability_key`
- `definition`
- `lifecycle_status`

These are infrastructure resources that live alongside runtime profiles, provider accounts, and model aliases.

### 2. Pack-defined composed tools

Inside a challenge pack, the optional top-level `tools` block lets a pack author define custom tool interfaces that the evaluated agent can see.

Those definitions are pack-local. They are part of the authored benchmark bundle.

### 3. Engine primitives

At the bottom are the built-in executor primitives, like `http_request`. These are the concrete operations the runtime knows how to execute safely.

A pack-defined tool can delegate to a primitive. That is the key distinction.

## Primitive versus composed tool

The current validation code expects composed tools to look roughly like this:

```yaml
tools:
  custom:
    - name: check_inventory
      description: Check inventory by SKU
      parameters:
        type: object
        properties:
          sku:
            type: string
      implementation:
        primitive: http_request
        args:
          method: GET
          url: https://api.example.com/inventory/${sku}
          headers:
            Authorization: Bearer ${secrets.INVENTORY_API_KEY}
```

What this means:

- `check_inventory` is the tool name the agent sees
- `http_request` is the engine primitive that actually runs
- `args` is the templated mapping from tool parameters to primitive inputs

So when people ask “primitive tools vs actual tools,” the clean answer is:

- primitives are built-in executor operations
- composed tools are the author-defined tool contracts that delegate to those primitives
- workspace tool resources are a separate infrastructure surface

## Validation is strict on purpose

The current parser and tests already reject several dangerous or ambiguous cases:

- unknown template placeholders like `${missing}`
- self-referencing tools where a tool delegates to itself
- delegation cycles across composed tools
- invalid JSON-schema parameter definitions
- missing primitive names or missing args blocks

That strictness is good. A benchmark bundle should fail at publish time rather than fail mysteriously at run time.

## Tool kinds are a separate gate from tool names

The sandbox policy also carries `allowed_tool_kinds`. That means the pack can say which broad categories are available, for example:

- `file`
- `shell`
- `network`

This is different from a specific composed-tool name. A pack might define `check_inventory`, but the runtime still checks whether the underlying kind is allowed.

## Internet access is not automatic

The current runtime does not treat network as free ambient capability.

There are at least three control points visible in the repo:

- the sandbox/tool policy starts with network disabled by default
- the pack can enable outbound networking through `sandbox.network_access` and related policy toggles
- the `http_request` primitive validates the target URL and CIDR allowlist before making a request

The current `http_request.py` helper does all of this:

- allows only `http` and `https`
- rejects missing hosts
- resolves DNS and checks resolved addresses
- blocks private, loopback, link-local, reserved, and multicast addresses unless explicitly allowlisted
- enforces request and response body limits
- sanitizes error handling so secret-bearing values do not leak back to the agent

So the current answer to “how can you call the external internet?” is:

- use a tool path that ultimately delegates to a network-capable primitive like `http_request`
- enable network access in the pack/runtime policy
- keep the destination within the permitted network rules

## Secrets live outside the pack

The product already exposes workspace-scoped secrets as a first-class surface.

You can:

- list secret keys
- set a secret value
- delete a secret

The list endpoint intentionally returns metadata only. Secret values never come back out.

The CLI surface is:

```bash
agentclash secret list
agentclash secret set <KEY>
agentclash secret delete <KEY>
```

## Where secret references resolve

There are two distinct secret-reference patterns in the current code:

- `workspace-secret://KEY` for provider credential resolution
- `${secrets.KEY}` inside composed-tool argument templates

These are not interchangeable.

`workspace-secret://KEY` is used when the provider layer resolves account credentials.

`${secrets.KEY}` is used during composed-tool argument substitution. The engine then decides whether the target primitive is allowed to receive secret-bearing args.

## Only hardened primitives can accept `${secrets.*}`

This is a security boundary, not a convenience feature.

The current `primitive_secrets.go` file says only secret-safe primitives may receive `${secrets.*}` substitutions, and today that allowlist intentionally includes only `http_request`.

The reason is straightforward:

- secrets must not end up in argv
- secrets must not land in readable sandbox files
- secrets must not come back in response headers or stderr
- secrets must not be echoed into the agent context accidentally

That is also why sandbox `env_vars` are literal-only. The executor explicitly rejects `${...}` placeholders there, and the code comment tells pack authors to use `http_request` headers instead when remote authentication is needed.

## See also

- [Write a Challenge Pack](../guides/write-a-challenge-pack)
- [Configure Runtime Resources](../guides/configure-runtime-resources)
- [Sandbox Layer](../architecture/sandbox-layer)
- [Artifacts](../concepts/artifacts)