Connecting several AI providers sounds like a simple dropdown until their authentication, streaming, tool formats, token accounting, errors, and safety rules differ. Nerva’s planned provider adapters should hide protocol differences without hiding the consequences of choosing a route.

Keep the internal request stable

Nerva can represent a task with a provider-neutral request:

messages, selected context, capability needs, max output, tool policy

An adapter translates that request into the provider’s API format and translates the response back into a stable internal result. The task manager can then record model name, provider, latency, usage information when available, and any failure.

Adapters should not own permissions

An adapter may know how to call an API. It should not decide whether a private file can be sent there. The context firewall prepares the approved payload, and the permission engine authorizes network access. This keeps provider integration from becoming an accidental privacy bypass.

Errors need the same discipline. A provider timeout should not cause an automatic request to another provider with the same sensitive context. Nerva can offer a fallback, but the user should see the new destination and approve a changed route when required.

Provider-agnostic design is valuable because it gives users choice, but the promise should remain honest. Compatible APIs still have their own terms, quotas, prices, and availability. Nerva can make those differences easier to inspect; it cannot remove them.

The useful design question

The useful question here is not whether an AI agent can produce an impressive demo. It is whether the workflow stays understandable when the task is incomplete, the repository is messy, or the model is wrong. For this part of Nerva, the focus is hiding provider-specific differences behind a clear adapter contract. That means each state should have a visible owner, a small input, and a result that another part of the system can inspect.

A concrete scenario

Consider mapping timeout, rate-limit, and refusal errors into states the task manager can explain. A good Nerva run would first state the scope, identify the files or operation it needs, and show the next proposed step. It would keep the original request separate from model-generated instructions. If an action needs approval, the user would see what will happen before it happens. Afterward, the task history would retain the command, result, and verification status instead of reducing everything to a confident paragraph.

This approach also makes a failure useful. A denied permission, unavailable provider, missing package, or changed file is information about the task state. Nerva should preserve it and explain the smallest recovery option. It should not silently broaden the request, retry a side effect, or claim completion because a model supplied plausible-looking text.

What I would test first

For an early implementation, I would test three paths: a normal successful run, a denied action, and an interrupted run resumed after the workspace changes. The key test is how a provider change affects privacy and approval rather than just price. In each path, the interface should make clear what Nerva knows, what it proposed, what actually ran, and what remains unverified.

Useful acceptance checks include:

  • the user can inspect the selected context before model execution;
  • sensitive paths and credentials are excluded or redacted;
  • every side effect has a narrow permission decision;
  • failures remain attached to the step that caused them;
  • a final answer links to evidence instead of implying that unrun work succeeded.

Nerva is still an upcoming project, so these are design and implementation goals rather than claims that a finished product already provides them. That distinction matters: a trustworthy agent should earn confidence through observable behavior, not through a feature list.

The boundary that matters in production

An adapter should expose capability information rather than pretending all providers behave the same. One route may support tool calling, another may accept only text, and a local model may have a smaller context window. The router can use those facts to reject an impossible plan early. Provider-neutral code is valuable only when the differences remain visible at the boundary.

For the first vertical slice, keep the boundary small enough to explain in a code review. Define the input, the decision, the side effect, and the evidence for completion. Add a test for the denied path as well as the successful path. This is where a local-first design earns trust: the user can inspect the context and history on the device, see when a provider is involved, and stop before an action crosses the permission boundary. The design should remain honest about its limits. Nerva is planned software, not a claim that every workflow can be made safe automatically. A clear “cannot verify” state is more useful than a polished but unsupported success message.

A review of this design should use a small fixture repository and record both allowed and rejected outcomes. That keeps the discussion concrete: reviewers can compare the requested scope with the selected context, action, and evidence. It also prevents Nerva from being judged only by how persuasive its response sounds.

The design is informed by the boundaries I have had to think through in CryptoEx and SentinelFi: backend work becomes easier to review when context, permissions, side effects, and verification are explicit.

A final implementation note is to keep this behavior observable in logs and in the interface. A developer should be able to inspect the decision after the task ends, not only while a spinner is running.