---
title: "Declare the public API and hide the rest · Agent Wranglers"
url: https://agentwranglers.se/playbook/engineering/libraries-and-sdks/declare-public-api
id: ENG-50
level: Recommended
updated: 2026-10-22
tokens: 773
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Declare the public API and hide the rest

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Libraries and SDKs](https://agentwranglers.se/playbook/engineering/libraries-and-sdks.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers.md). Updated 2026-10-22.

- ID: ENG-50
- Level: Recommended
- Chapter: [Libraries and SDKs](https://agentwranglers.se/playbook/engineering/libraries-and-sdks.md)
- Rule: State in code which modules, functions and types of a library are public. Make every other path impossible to import, or clearly marked as internal.
- Check: A test in a separate consumer project imports an internal path of the built package and fails. In JavaScript the import throws `ERR_PACKAGE_PATH_NOT_EXPORTED`.
- How: Semantic versioning starts with a declared public API, because a version number only promises something about it. Users import whatever they can reach, and then every internal rename breaks them. In JavaScript, list the public entry points in the `exports` field of `package.json`. In Python, set `__all__` and start internal modules with an underscore. Go has `internal/` folders, Rust has `pub(crate)`, and Java has module exports. The version check in [Check every release against the public API](https://agentwranglers.se/playbook/engineering/libraries-and-sdks/semver-check.md) reads this list.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### JSON example

```json
{
  "name": "@example/invoices",
  "exports": {
    ".": "./dist/index.js",
    "./testing": "./dist/testing.js"
  }
}
```

### TypeScript example

```ts
// src/index.ts: everything a user may import
export { createInvoice, voidInvoice } from './invoices';
export type { Invoice, InvoiceLine } from './types';
```

### Python example

```python
# invoices/__init__.py: everything a user may import
from invoices._core import create_invoice, void_invoice
from invoices._types import Invoice, InvoiceLine

__all__ = ["create_invoice", "void_invoice", "Invoice", "InvoiceLine"]
```

## Sources

- [Semantic Versioning 2.0.0](https://semver.org/)

## Related rules

- ENG-51 [Check every release against the public API](https://agentwranglers.se/playbook/engineering/libraries-and-sdks/semver-check.md) in Engineering

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/engineering/libraries-and-sdks/declare-public-api">Agent Wranglers engineering playbook</a>`. In code you write, add a comment next to it with the same link.

- Next: [Check every release against the public API](https://agentwranglers.se/playbook/engineering/libraries-and-sdks/semver-check.md)
- [Libraries and SDKs](https://agentwranglers.se/playbook/engineering/libraries-and-sdks.md)
