# Private tools

A private tool is one your project brings: an internal service, a provider nobody has written a connector for yet, or a variant of a shared one shaped to how you work. It is visible to your project and to nobody else.

The console screen for this is **Build**. Everything below describes what that screen does, so you can do it from code as well.

Three things that screen no longer says on itself, because they belong here. It does not gate a draft: a draft is inert until a gate run passes, and the run is a control on the draft's own row. It does not judge a document either; the loader does, over Validate, which is why a refusal reads in the loader's words. Connecting an account for an app is the **Connect** screen, and what an agent may then do with it is **Policies**.

## Three rules

**Private only.** Every submission carries your project, and nothing on this path can write, replace, or delete an entry of the shared catalog.

**Validated by the same loader, plus one more check.** A submission is refused for everything a committed connector file would be refused for, and for one thing beyond that: the address it calls has to be HTTPS, and its host may not be loopback, a private range, or link-local. A committed file is written by whoever runs the machine. This path takes any project key, and the address it stores is an address the server will go and call.

**Measured before it is served.** An accepted submission is stored as a draft, outside the served catalog. It reaches no search result and no execution until it passes the gate.

## Write it

A tool definition is three documents: the tools themselves, the phrases that help search find them, and the cases that prove search does.

Check as you write, without storing anything, by submitting with validate-only set. The loader that will accept or refuse the real submission is what answers, naming the field and the reason, so you are never working against your memory of the rules.

A refusal comes back on a successful call, because a refusal is the answer the request asked for. The call itself still fails for the reasons any call fails: a key without the approver role, or a server that cannot reach its store.

The written specification of the format is maintained for people writing connectors for the shared catalog rather than for people using atmon, so it is not in this documentation. Ask us for it and we will send it; the address is on the [contact page](https://atmon.ai/pricing).

## Submit it

The three documents go over the wire as text. The loader is the one definition of that format, and a second copy of it in a request schema would fork it, so the text is what travels. Every JSON document is valid YAML, so send JSON if you prefer.

What comes back echoes what was accepted, including the list of tools that count as destructive. Read that list. You are the approver for your own tools, and this echo is your chance to notice a class you did not mean to create.

## Gate it

A draft serves nobody. Gating measures it: your cases are run against the whole set it will compete in, the shared catalog plus your project's other active private tools.

A score means nothing without the set that produced it, so the report says how large that set was alongside the result. When it fails, the report names the cases that missed and what was returned instead, which is usually enough to see whether the phrases are wrong or the tool descriptions are.

A tool that passes goes active and starts appearing in search results for your project. A tool that fails stays a draft.

## After that

A private tool goes through exactly the same path as any other: the destructive gate, the rules, credential resolution, the pace limits, the retries, the shaping, and the receipt. Your allowed and denied lists, your per-person visibility, your approval gate, and your rate ceilings all apply to it. It is an entry in a catalog, not a way around one.

The calls behind this screen are not in the public [API reference](../reference/api/index.md), because managing your own catalog is something a person does on a screen or an operator does on a machine, rather than something a product calls on a request path. The console does it, and so can a script pointed at your own node.
