Skip to main content
The cognis::tools::* module ships generally-useful tools — Calculator, FilesystemTool, HttpRequest, JsonQuery, OpenApiTool, PythonRepl, HumanTool. If you’ve built a tool that you think belongs in the standard library — clear scope, broad utility, no proprietary backend — this page covers how to land it.

Is it a fit?

Built-in tools should be:
  • General-purpose. Useful in many domains, not just yours.
  • Self-contained. No external service required for the basic shape (or behind a feature flag if needed).
  • Predictable. Stable behavior the model can rely on. No “sometimes returns the right answer.”
  • Safe by default. A tool that runs code or fetches URLs ships with conservative limits.
If your tool is domain-specific (a calculator for your insurance product, a search over your private knowledge base), it lives in your codebase, not Cognis. The Tool trait is stable enough that you can ship it from a downstream crate.

What you’ll add

  • A new module under crates/cognis/src/tools/<name>.rs.
  • A struct implementing Tool (or SchemaBasedTool for typed convenience).
  • Tests covering normal use, error cases, and any safety limits.
  • An entry in cognis::tools::* exports.
  • An example under examples/tools/.
  • A doc entry in Tools.

Step 1 — Define the tool

Two shapes; pick whichever fits.

Step 2 — Wire up the description

The description is what the model reads to decide whether to call you. Make it good:
  • Lead with the verb. “Count the number of words” beats “A function for word counting.”
  • Mention the units. “Returns a number.” vs “Returns a JSON object with word_count.”
  • Don’t promise capabilities you don’t have. Models will try.
Field doc-comments matter too — /// The text to count words in. becomes the JSON Schema description. The model uses it.

Step 3 — Validators (where it makes sense)

For tools that take strings, numbers, or enums, declare validators on the args struct:
These show up in the JSON Schema and run as runtime checks before execute_typed is called.

Step 4 — Safety

Built-in tools should ship with safety defaults:
  • HTTP tools — block internal networks (RFC1918, link-local) by default. Allow-list via builder.
  • Filesystem tools — gate by a Backend. No raw std::fs::read against arbitrary paths.
  • Code execution — sandbox or constrain. Calculators should be expression evaluators, not eval.
  • Long-running — time out. Don’t let the model wedge an agent on a slow tool.
If your tool needs configuration to be safe (allow-list, sandbox path), make that configuration required in the builder, not optional.

Step 5 — Tests

Cover:
  • The happy path.
  • Argument validation — invalid inputs get a clear error before the body runs.
  • Edge cases — empty input, max-size input, unicode.
  • Safety — for an HTTP tool, a test that internal IPs are blocked.

Step 6 — Re-export

The umbrella’s top-level re-exports include pub use tools::*, so consumers will see cognis::WordCountTool.

Step 7 — Example

Register as tools_word_count.

Step 8 — Document

Add a row in Tools → Built-in tools.

Step 9 — PR

Title: feat(tools): add WordCountTool. Description:
  • What it does.
  • Why it belongs in the standard library (not just in your downstream code).
  • Safety defaults.
  • Tested coverage.

See also

Tools

User guide for the trait shape.

Adding a provider

Different domain, same shape.

Architecture

Where your tool lands in the workspace.