> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cynative.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Cynative Architecture: Single Binary, No External State

> Cynative is a single static Go binary. Understand the agent loop, tool system, action gate, JS sandbox, connectors, and audit pipeline.

Cynative is a single static Go binary built with Go 1.27 and cobra. There is no server process, no external state, and no daemon to manage — the entire system lives in one executable. Running `cynative` starts a cobra CLI that drives an LLM research loop directly from your shell, using the credentials already present in your environment.

## Components

<CardGroup cols={2}>
  <Card title="CLI" icon="terminal">
    Cobra commands: `root` (interactive session and `-p` single-task mode), `doctor` (validates configuration and connector readiness), and `agents` (lists and shows built-in and user agents). Entry point is `cmd/cynative`, which calls `cli.Execute()` and exits with `cli.ExitCodeFor(err)`.
  </Card>

  <Card title="Agent loop" icon="rotate">
    Drives the model through a research iteration. Bounded by `max_iterations`, `max_total_tokens`, and `max_consecutive_failures`. The orchestration tools `write_todos`, `task`, and `verify_findings` live here (in `internal/agent`) because they drive the loop's unexported `runState` — they are registered without the approval wrapper because they perform no credentialed I/O.
  </Card>

  <Card title="Tools" icon="wrench">
    The two I/O primitives are `http_request` and `code_execution`. Both are wrapped in an approval decorator at the top level. `api_reference` is the only I/O tool without the approval wrapper — it reads public vendor metadata or, for Kubernetes connectors, the target cluster's own OpenAPI documents, and implements `UngatedIO`. Scripts inside `code_execution` call inner tools with no approval prompt; each tool must enforce its own gates.
  </Card>

  <Card title="Action gate" icon="shield-check">
    Resolves every tool call to its required IAM actions — derived from the providers' own API definitions — then authorizes against the configured policy before any credential is attached. The gate fails closed: an unclassifiable request, a missing catalog, an unresolved permission, or an unparseable verifier verdict all result in a denial. Policy defaults are `SecurityAudit` (AWS), `roles/viewer` (GCP), and `Reader` (Azure).
  </Card>

  <Card title="Network layer" icon="network-wired">
    Pins every request host to its mapped service and region. On a direct route (no proxy configured, or a `NO_PROXY` match) it verifies the resolved IP before connecting. When the operator's proxy policy selects a proxy, the connection goes only to that proxy's canonical authority. `https://` is the only allowed scheme; redirects are disabled, and the `Host` header is rejected.
  </Card>

  <Card title="JS sandbox" icon="box">
    An embedded sobek JavaScript runtime. Model-written scripts have no network, filesystem, or package access — only the exposed tools are reachable, as async functions. `Run` cancels the run context before closing `s.done`, and a worker that wins a concurrency slot re-reads that context inside the winning arm before calling any tool. Scripts run under a timeout (default 120 s) and a capped output size.
  </Card>

  <Card title="Connectors" icon="plug">
    AWS, GCP, Azure, EKS, GKE, AKS, self-managed Kubernetes, GitHub, and GitLab. Connectors use the credentials already present in the shell — there is no separate credential store. For AWS assumed-role identities, credentials are re-vended via STS `AssumeRole` scoped to a managed read-only policy so IAM enforces the boundary independently of the gate.
  </Card>

  <Card title="Audit log" icon="file-lines">
    An append-only JSONL log written to `~/.cynative/audit.log` by default. The log is fail-closed: if a call cannot be recorded the run aborts. A write failure latches — every later `Log` returns the error and writes nothing, and the closer reports the failure at exit. Tool results are redacted before being written; approval-prompt arguments are stored verbatim.
  </Card>
</CardGroup>

## Request flow

<Steps>
  <Step title="Model decision">
    The model decides whether to produce an answer directly or invoke a tool. If it calls a tool, the agent loop dispatches the call.
  </Step>

  <Step title="Action gate">
    The action gate resolves the call to its required IAM actions and checks them against the configured read-only policy. Denials return an error to the model and the loop continues. Unclassifiable requests are denied — the gate never falls back to allow.
  </Step>

  <Step title="Network layer">
    For allowed calls, the network layer pins the request host to its mapped service and region. On a direct route it verifies the resolved IP before opening the connection; on a proxied route it connects only to the proxy.
  </Step>

  <Step title="Credential injection">
    Only after the gate authorizes the call are credentials attached to the outgoing request. The model never holds credentials directly.
  </Step>

  <Step title="Provider response">
    The request reaches the cloud or platform provider. The response is returned through the transport layer, which redacts secrets before the result travels any further.
  </Step>

  <Step title="Audit record">
    Every call is written to the audit log as a JSONL record, including the decision, route, and outcome. A failed write aborts the run.
  </Step>

  <Step title="Result back to model">
    The redacted result is fenced as untrusted content and re-enters the transcript. The loop then repeats until the model produces an answer or a bound trips (`max_iterations`, `max_total_tokens`, or `max_consecutive_failures`).
  </Step>
</Steps>

## Package map

| Package | Responsibility |
| - | - |
| `cmd/cynative` | `main`; calls `cli.Execute()` and exits with `cli.ExitCodeFor(err)`. |
| `about.go`, `agents.go` (module root) | `go:embed` of `README.md` and `agents/`; at the root because embed cannot reach a parent directory. |
| `internal/cli` | Cobra commands (`root`, `doctor`, `agents`), the composition root, exit codes, signal handling. |
| `internal/agent` | The research loop; `write_todos`, `task`, `verify_findings`; untrusted fencing; halt conditions. |
| `internal/agentcatalog` | Named markdown agents for `--agent`; user tier plus embedded built-ins; closed frontmatter schema. |
| `internal/apiref` | Connector-neutral operation reference types and the hint matcher behind `api_reference`; stdlib only. |
| `internal/schema` | Provider-agnostic message and tool types; pure leaf. |
| `internal/llm` | Bifrost adapter behind `schema.ChatModel`; derived provider catalog; env-var resolution. |
| `internal/tools` | The I/O tools `http_request` and `code_execution`, plus the approval decorator. |
| `internal/sandbox` | sobek JS runtime; tools exposed as async functions; rebuild-when-unusable rule. |
| `internal/transport` | Executes `http_request`: HTTPS only, no redirects, `Host` header rejected, dial-time IP guard, redaction on both exits. |
| `internal/auth` | Connector registry and the shared gates (`AuthorizeHost`, `AuthorizeAction`, `AuthorizeAddr`, `Inject`). |
| `internal/auth/authreq` | The narrowed views (`View`, `AuditView`, `ProviderArgs`) the gates receive; stdlib only. |
| `internal/auth/authtest` | Fake providers for tests; test-only import — never imported from non-test code. |
| `internal/auth/aws`, `gcp`, `azure` | Per-cloud host pinning and action authorization against a configured read-only policy or role. |
| `internal/auth/k8s` | Shared Kubernetes request classifier and RBAC matcher for `eks`, `gke`, `aks`, and `kubernetes`; also the OpenAPI root parser, streaming pass, pre-pass index, and distiller behind the targeted reference of all four Kubernetes connectors. |
| `internal/auth/github`, `gitlab` | Request classifiers behind a per-category exposure ceiling. |
| `internal/auth/openapidoc` | The OpenAPI 3 docs core behind `api_reference` for `github`, `gitlab`, and the Kubernetes connectors; imports only the standard library and `internal/apiref`. |
| `internal/auth/exposure`, `internal/auth/cloudauth` | Leaves: `exposure` is the exposure-level lattice behind `github` and `gitlab`; `cloudauth` is the host normalizer and fetch shells behind `aws`, `gcp`, and `azure`. |
| `internal/cache` | On-disk TTL cache primitive. |
| `internal/config` | Loader for `~/.cynative/config.yaml` and the `CYNATIVE_*` env vars derived from struct tags; validators. |
| `internal/audit` | Fail-closed JSONL audit log and the per-call recorders (`Scope`, `Decision`, `Failure`, `Fatal`). |
| `internal/redact` | Secret redactor wired at transport responses, sandbox tool results, every model call, every line the Bifrost SDK logs, the audit log, and doctor output. |
| `internal/metrics` | Session-cumulative telemetry and the token budget. |
| `internal/ui` | Glamour rendering, approval prompter, raw-mode line editor, terminal controller. |
| `internal/interrupt` | Two-stage interrupt state shared by `cli` and `ui`. |

## Composition spine

The dependency spine runs in one direction:

```text theme={null}
cmd -> cli -> agent -> tools -> transport -> auth
```

`newDeps` in `internal/cli/wire_shell.go` is the composition root — the single place where all dependencies are wired together. Every external dependency (cloud SDKs, OS, filesystem, network, stdio, terminal, the Bifrost client, the sobek runtime) is a constructor-injected interface or function field defaulted to the real implementation. The process environment is read only in the composition root and in `*_shell.go` files.

## Key invariants

**The model never holds credentials.** Credentials are attached only after the action gate has authorized the call. The model receives only redacted tool results.

**The gate fails closed on unclassifiable requests.** If a request matches no operation in the connector's metadata, the gate denies it. There is no allow fallback for ambiguous or unknown calls.

**Per-run mutable state lives on `runState`, not on `*Agent`.** Concurrent runs, each with their own `task` sub-runs, share one `Agent` instance. Putting mutable state on `runState` (in `internal/agent/loop.go`) keeps concurrent runs isolated and race-free.

**JS sandbox: cancel context before close, worker re-reads context inside winning arm.** `Run` cancels the run context before it closes `s.done`. A worker that wins a concurrency slot re-reads that context inside the winning arm before it calls the tool. Both halves are load-bearing: a script can end its run with the context still live by throwing out of the IIFE wrapper, and the acquire `select` can have both arms ready at once, so neither signal alone is sufficient to determine the run is over.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.