# How ACP/ACPX Agent Targeting Works with acp_registry_overrides in no-mistakes

> Learn how ACP/ACPX agent targeting works with acp_registry_overrides in no-mistakes. Discover how custom commands are injected for precise agent control.

- Repository: [Kun Chen/no-mistakes](https://github.com/kunchenguid/no-mistakes)
- Tags: internals
- Published: 2026-07-03

---

**When you specify an agent as `acp:<target>` in no-mistakes, the `acp_registry_overrides` configuration map substitutes the target name with a custom raw command, injecting it via the `--agent` flag when spawning the `acpx` binary.**

The `no-mistakes` repository supports external ACP agents through the `acpx` binary, allowing users to extend functionality with custom agent implementations. The `acp_registry_overrides` configuration option provides a flexible mechanism to remap agent targets to arbitrary commands without modifying the underlying agent code. Understanding how ACP/acpx agent targeting works with `acp_registry_overrides` enables precise control over agent execution workflows.

## Understanding the ACP/ACPX Agent Pattern

ACP agents in `no-mistakes` operate by invoking an external `acpx` binary with specific arguments. When you configure an agent name prefixed with `acp:`, the system recognizes it as an external agent target rather than a built-in implementation. This design delegates agent logic to external processes while maintaining a consistent internal interface.

The targeting mechanism relies on three core components: target detection in [`internal/agent/agent.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/agent/agent.go), registry override resolution, and command-line construction in [`internal/agent/acpx.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/agent/acpx.go).

## Target Detection and Validation

### How acpTarget Extracts the Target Name

The `acpTarget` helper function in [`internal/agent/agent.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/agent/agent.go) validates and extracts the target portion from agent names. It strips the `acp:` prefix and enforces strict validation rules to prevent malformed targets.

```go
// internal/agent/agent.go
func acpTarget(name types.AgentName) (string, bool) {
    if !strings.HasPrefix(string(name), "acp:") { return "", false }
    target := strings.TrimPrefix(string(name), "acp:")
    if target == "" || strings.ContainsAny(target, " \t\r\n") { return "", false }
    return target, true
}

```

This function ensures that target names are non-empty and contain no whitespace characters before proceeding to registry lookup.

## Registry Override Resolution

### The ACPRegistryOverrides Map

When constructing an agent via `NewWithOptions`, the system checks for registry overrides in the `Options` struct. If `ACPRegistryOverrides` contains an entry matching the extracted target, that value becomes the **raw command** for the agent.

```go
// internal/agent/agent.go (NewWithOptions)
if target, ok := acpTarget(name); ok {
    rawCommand := ""
    if opts.ACPRegistryOverrides != nil {
        rawCommand = opts.ACPRegistryOverrides[target]
    }
    return &acpxAgent{bin: bin, target: target, rawCommand: rawCommand}, nil
}

```

The `acpxAgent` struct stores this raw command for later use during argument building, maintaining a clean separation between target identification and command resolution.

## Command Construction with buildArgs

The `acpxAgent.buildArgs` method determines how the final command line is assembled based on whether a registry override exists. When `rawCommand` is populated, it injects the `--agent` flag; otherwise, it falls back to passing the target name directly.

```go
// internal/agent/acpx.go (buildArgs)
if a.rawCommand != "" {
    args = append(args, "--agent", a.rawCommand)
}
…
if a.rawCommand == "" {
    args = append(args, a.target)          // fall‑back to target name
}
args = append(args, "exec", prompt)

```

This conditional logic ensures that registry overrides take precedence while maintaining backward compatibility for standard target names.

## Configuration Wiring in YAML

The `acp_registry_overrides` field in your configuration file maps directly to the `Config.ACPRegistryOverrides` map in [`internal/config/config.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/config/config.go).

```go
// internal/config/config.go (excerpt)
type Config struct {
    ACPXPath             string            `yaml:"acpx_path"`
    ACPRegistryOverrides map[string]string `yaml:"acp_registry_overrides"`
}

```

When the CLI loads `~/.no-mistakes/config.yaml`, it unmarshals this structure and forwards the overrides map to `agent.NewWithOptions`. A typical configuration looks like:

```yaml

# ~/.no-mistakes/config.yaml

agent: acp:local-gemini
acpx_path: /usr/local/bin/acpx
acp_registry_overrides:
  local-gemini: node /opt/mock-acp-agent.mjs

```

This configuration causes the `acp:local-gemini` agent to execute as `acpx --agent "node /opt/mock-acp-agent.mjs" exec "<prompt>"`.

## Practical Implementation Examples

### Programmatic Agent Creation

You can instantiate ACP agents with registry overrides directly in Go code:

```go
opts := agent.Options{
    ACPRegistryOverrides: map[string]string{
        "local-gemini": "node /tmp/mock-acp.mjs",
    },
}
a, _ := agent.NewWithOptions("acp:local-gemini", "/usr/local/bin/acpx", nil, opts)
fmt.Println(a.Name()) // → "acp:local-gemini"
cmdArgs := a.(*acpxAgent).buildArgs(agent.RunOpts{Prompt: "do work", CWD: "/repo"})
fmt.Println(cmdArgs)
// Output:
// ["--agent" "node /tmp/mock-acp.mjs" "--format" "json" ... "exec" "do work"]

```

### YAML Configuration Setup

For CLI usage, define your overrides in the configuration file:

```yaml
acp_registry_overrides:
  local-gemini: node /opt/mock-acp-agent.mjs
  custom-bridge: /usr/local/bin/custom-agent --mode=production

```

The daemon automatically loads these mappings when initializing the agent pool, applying them to any matching `acp:<target>` agent requests.

## Summary

- **Target detection** occurs via `acpTarget` in [`internal/agent/agent.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/agent/agent.go), which validates `acp:` prefixes and extracts clean target names.
- **Registry overrides** are stored in `ACPRegistryOverrides` and resolved during agent construction in `NewWithOptions`.
- **Command injection** happens in `acpxAgent.buildArgs` through the `--agent` flag when overrides exist, falling back to the target name otherwise.
- **Configuration binding** maps the YAML `acp_registry_overrides` field to the internal config struct in [`internal/config/config.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/config/config.go).
- **External execution** ultimately invokes the `acpx` binary with the resolved arguments, enabling custom agent logic without code changes.

## Frequently Asked Questions

### What happens if no registry override exists for an ACP target?

If `ACPRegistryOverrides` is nil or lacks an entry for the specific target, the `acpxAgent` passes the plain target name as a positional argument to the binary instead of using the `--agent` flag. This fallback behavior allows standard `acpx` registry lookups to function normally when no custom override is defined.

### Can I override multiple ACP agents in the same configuration?

Yes, the `acp_registry_overrides` map supports multiple key-value pairs simultaneously. You can define distinct raw commands for different targets such as `gemini`, `claude`, or custom identifiers, and the system will resolve each independently based on the agent name requested.

### What validation is performed on the target name?

The `acpTarget` function enforces that extracted targets are non-empty and contain no whitespace characters (spaces, tabs, carriage returns, or newlines). This validation prevents command injection and ensures that target names are valid identifiers before attempting registry lookups.

### How does the acpx binary receive the override command?

When an override exists, the `buildArgs` method appends the literal string `"--agent"` followed by the raw command value to the argument slice. This occurs before the `exec` subcommand and prompt payload, positioning the override as a top-level flag that the `acpx` binary processes to determine which agent implementation to execute.