Osy#the first language built for agents
Agents firstAgentic appsWorkflowsDurable Execution — built inSecurityTestingThe editorThe UI modelOne program

Reference / Types

namespace

namespace Shop.Catalog;

Declares the namespace a file's types belong to, written once at the top of the file. It is optional — a file without one puts its types in the global namespace. Names resolve against the namespace a file is written in, then any imported namespaces, then the always-available `Osyrin` core.

stable3 examples compiled by CItypesnamespaceauthoring

Summary#

A namespace groups a file's types under a common name, so two parts of an app can each have an Order without colliding. Write it once, at the top of the file, terminated by a semicolon:

namespace Shop.Catalog;

It is optional. A file with no namespace declaration puts its types in the global namespace — which is exactly what a single-file app wants, and what every example in this reference assumes.

Signature#

namespace Shop;              // this file's types are Shop.*
entity Order { … }           // → Shop.Order

Description#

What it does to a name#

A type declared in a namespace gets that namespace as a prefix. namespace Shop; followed by entity Order declares Shop.Order — that is the type's real, full name, the one you use to refer to it from elsewhere.

Inside the file that declares it, you just write Order.

Two forms — file-scoped and braced#

Osy# supports both C# forms:

namespace Shop;                          // file-scoped — opens the whole file (preferred)

namespace Shop { entity Order { … } }    // braced — opens just its block
namespace Billing { entity Order { … } } // several braced namespaces may share one file
  • File-scoped (namespace X;) opens the whole file: it must come before every other declaration, and a file may declare at most one. Prefer it for a file that is all one namespace.
  • Braced (namespace X { … }) opens just its block, so a file may hold several and they may nest (namespace Shop { namespace Catalog { … } } puts a type in Shop.Catalog). This is what lets C# code paste in verbatim.

A file uses one form or the other, never both — mixing a file-scoped namespace X; with a braced namespace Y { … } in the same file is an error (as in C#).

How a name resolves#

When you write a bare name, it is looked for in this order — the first match wins, and no later step can make it ambiguous:

  1. The namespace you're in, then each enclosing one, working outward. Inside namespace Shop.Catalog; that means Shop.Catalog, then Shop, then the global namespace.
  2. The namespaces you imported with a using declaration. If two imports offer the same name, that is an error — qualify the reference to say which you mean.
  3. The Osyrin core, the platform's own namespace, always available without importing anything.

Because step 1 comes first, a type you declared always wins over one you imported. To reach the imported one anyway, write its full name.

The Osyrin namespace is the platform's#

Everything the platform ships lives under Osyrin. Its core types need no import. Its optional capabilities are sub-namespaces — Osyrin.Memory, Osyrin.Storage, Osyrin.Ui, … — that you first depend on with a use in your app { } manifest, then import with a using in each file that references their names. You cannot declare a type in Osyrin yourself.

Reaching another namespace#

A sibling namespace's types are not visible bare — qualify them, exactly as in C#:

namespace Billing;

int Count() {
  var orders = Shop.Order.Where(o => o.Code == "x").ToList();   // qualified
  return orders.Count;
}

Declaration names never contain a dot#

entity Shop.Order is an error. A dot in a declared name is how you'd spell a namespace, not how you declare one — use namespace Shop; at the top of the file.

Examples#

// catalog.osy
namespace Shop;

entity Order {
  [Required] string Code;
  decimal Total;
}

int OpenOrders() {
  // `Order` resolves to Shop.Order — the namespace this file is written in.
  return Order.Where(o => o.Total > 0).ToList().Count;
}
// billing.osy — a different namespace, so Shop.Order must be qualified.
namespace Billing;

entity Invoice {
  Shop.Order Source;
  decimal Amount;
}

Step 3 applies in every position a type name can appear, including a property's type — a core type needs no import there either:

namespace Filing;

entity Attachment {
  // `MarkdownDocument` is `Osyrin.MarkdownDocument`, found at step 3. Nothing is imported and nothing is qualified.
  MarkdownDocument Body;
}

See also#

  • useuse declares the capability dependency in the manifest; using imports its names in a file.
  • type visibility (public / internal)public and internal decide which of a namespace's types others can reach.
  • Osyrin.Ui (the UI kit)using brings a kit's public types into scope under their bare names.

Related

use

Declares a capability your app depends on, written inside the `app { }` manifest block. It provisions the capability…

type visibility (public / internal)

A top-level type carries a public or internal visibility that decides whether code outside its namespace can name it…

Osyrin.Ui (the UI kit)

The bundled UI kit — ready-made styled controls like `Button`, the shared design-system vocabularies (`Tone`, `Size`)…