A working engineer's mental model for the execution layer of the OpenTeams / Nebari platform — built from analogies, then simple code, then real orchestration, then a full system. Anchored the whole way to primitives you already use.
A Frame is the context (data/config you inherit), a Cog is a worker (a model oriented by Frames), and an Op is the orchestrated workflow that runs Cogs with human oversight. It's separation of concerns: config → compute → orchestration.
Notice the brand gradient runs blue → purple → coral. That's not decoration here — it's the reading order: Frame → Cog → Op. Each adds a layer of structure on top of the last.
Before any code, anchor the vocabulary. None of these concepts are new mechanically — they're new boundaries drawn around familiar pieces, so each can be versioned, governed, and reused independently. If you've shipped infrastructure, you've built all of this before; you just didn't have names that separated context from worker from workflow.
| Concept | What it is (whitepaper) | The primitive you already know |
|---|---|---|
| Frame | A scoped, versioned, inheritable text artifact carrying org context: rules, terminology, goals, style, norms, tool specs, prompts. | A merge of env/config files + a base class you extend + the CSS cascade + a checked-in .editorconfig/lint ruleset. Pure data, no behavior. |
| Cog | A discrete AI worker = a model + Frame-derived context + permitted tools + governance parameters. | A configured stateless worker / microservice. Think a Celery worker or a Lambda with an IAM role (governance) and env vars (frames). |
| Op | An installable, versioned, supervised workflow that orchestrates Cogs with human checkpoints. | A workflow / DAG (Airflow, Temporal) or a CI/CD pipeline — packaged and shipped like an npm/pip package. |
| Nebi | The packaging + reproducibility layer. Defines the common format; pins dependencies; logs installs. | pip / npm + a Dockerfile & lockfile. The distribution plumbing. |
| Nebari | The open-source infra stack the Hub is assembled from. | Kubernetes / the base distro your platform sits on. |
| Intelligence Hub | The org's owned, governed deployment where Frames/Cogs/Ops actually run. | Your VPC / cluster / tenant — your production environment, inside your perimeter. |
| Organizational Memory | The persistent context substrate: frame history + Cog conversations + Op run records. | Your databases + logs + vector store + git history, unified. |
| Marketplace | Where Frames/Cogs/Ops are published, discovered, and installed across Hubs. | The npm registry / Docker Hub / an app store. |
Each layer wraps the one below and adds structure. This is the spine of the whole architecture:
The word "agent" usually smushes context, a model, tools, and a control loop into one blob. That's like putting your config, business logic, and orchestration in a single function — it works until you need to version one without the others, share the config with a partner, audit one decision, or reuse the worker in a second workflow.
Splitting into Frame / Cog / Op is the single-responsibility principle applied to AI: what context applies (Frame, declarative), who does one unit of work (Cog), and how work is coordinated and approved (Op). Each gets its own version, its own owner, its own test surface, its own audit boundary.
The portable container for the context that makes AI work yours instead of generic.
Every org has implicit context — brand voice, terminology, regulatory constraints, team norms, project goals. Today it lives in style guides, wikis, Slack history, and senior employees' heads. A Frame makes that context an explicit, versioned, shareable artifact. Crucially, a Frame is data, not code: it carries what to know and respect, never what to do.
Picture onboarding a sharp contractor. Before they touch anything, you hand them the company handbook (values, voice, what "Customer" means here), then the team's playbook (how this team works), then the project brief (what we're shipping this quarter). Each layer is more specific and can override the last — your team's definition of a term beats the generic company one, exactly like a more specific CSS selector wins the cascade, or a subclass overrides a base method.
A Frame is that stack of handbooks — but machine-readable, version-controlled, and inheritable, so a human or a Cog can be oriented by it without a week of onboarding meetings.
A Frame ≈ a base class + the CSS cascade + a checked-in config file. Inheritance and override are the whole point.
A Frame ≈ the project charter + the team norms doc + the glossary — but one living artifact everyone (and every tool) reads from, not five stale wiki pages.
At its simplest, a Frame is a text file (or a folder of them) in an open format — human-readable, diff-able, and stored in git. Here's a brand-voice Frame:
scope: org
name: Acme Brand Voice
version: 2.3.0
extends: frame://acme/company@4.1 # parent frame — like a base class
---
## Style
Plain, direct American English. No hype words ("revolutionary",
"synergy"), no emoji. Active voice. Short sentences.
## Terminology
"Customer" = a paying merchant.
"Incident" = any Sev-1 / Sev-2 event.
## Rules
- Never disclose unreleased roadmap items in external copy.
And the same thing as an object, so we can reason about it in code. Note there is no behavior here — just structured context and a pointer to a parent:
@dataclass
class Frame:
name: str
scope: str # org | dept | team | project | role | user
version: str
extends: str | None = None # parent frame URI — the base class
sections: dict = field(default_factory=dict) # rules, terminology, style...
# A Frame is DATA, not code. It carries context, never actions.
brand_voice = Frame(
name="Acme Brand Voice",
scope="org",
version="2.3.0",
extends="frame://acme/company@4.1",
sections={
"style": "Plain, direct American English. No hype words, no emoji.",
"terminology": {"Customer": "a paying merchant"},
},
)
The power shows up when Frames stack. A Frame's five defining properties — scoped, inheritable, composable, shareable, discoverable — all fall out of treating context like a class hierarchy plus a config merge. At work-session time you compose several inheritance chains, and a more-specific Frame overrides a key set by a less-specific one.
The resolver is just an ordered merge that keeps an audit trail of who set what — conceptually identical to Python's method-resolution order, or merging config dicts, or Docker image layers:
def resolve(frames: list[Frame]) -> Context:
"""Compose frames least-specific -> most-specific.
Like Python's MRO, merging config dicts, or the CSS cascade:
a more-specific frame OVERRIDES a key set by a less-specific one."""
ctx, provenance = {}, {}
for frame in expand_inheritance(frames): # walk each parent chain first
for key, value in frame.sections.items():
ctx[key] = value # last writer wins (override)
provenance[key] = frame.version # keep WHO set WHAT — auditable
return Context(ctx, provenance)
# Composition for a work session = layering multiple chains together:
session = resolve([
company_frame, # who we are
payments_team_frame, # redefines "Customer" -> cardholder (overrides company)
q3_release_frame, # adds the freeze rule
pci_dss_frame, # adds compliance rules (attached by Legal)
my_personal_frame, # my review preferences (overrides style)
])
# Every Cog in this session is now oriented by `session` — no re-explaining.
At system scale a Frame is a first-class, governed artifact in a registry — pinned by version for reproducibility, published with a visibility scope, shared field-by-field with external partners, and gradable so feedback routes back to its accountable author.
registry = FrameRegistry(hub="acme.intelligence-hub.internal")
# Pin an exact version — reproducibility, exactly like a lockfile entry.
registry.install("frame://acme/legal/pci-dss@3.0")
# Publish with a visibility scope; children inherit when the parent bumps.
registry.publish(brand_voice, visibility="org")
# Selective, FIELD-LEVEL sharing to an external partner:
registry.share(
"frame://acme/eng/payments@1.4",
with_partner="vendor://stripe-integrations",
include=["terminology", "tools"], # share these
redact=["rules_pay", "rules_freeze"], # keep internal rules private
)
# Humans grade a frame; feedback routes to the accountable author for review.
registry.feedback("frame://acme/company@4.1", section="style", score=+1)
# feedback scale: -10, -1, -0, +0, +1, +10
A Frame is governed, inheritable context as data. It is not a prompt and not a system message you'd hand to a vendor API — it's an org-owned artifact that's versioned, audited, inherited, and exchanged. The context that fuels your AI's value stays with you.
The atomic unit of AI work — a model, oriented by Frames, with tools and a governance boundary.
A Cog is a discrete, AI-powered worker. It bundles four things: a model (possibly specialized), a context defined by one or more Frames, the tools it may call, and its governance parameters (what data it may read, what actions it may take, what needs a human). The model is the engine; the Frames are what make it your worker rather than a generic one.
A Cog is the contractor after they've read the handbooks (Frames). They have one specialty — review payments PRs, draft release notes, qualify a lead — a badge that opens only certain doors (governance), a specific set of tools on their belt, and they know they must escalate certain decisions to a human. You don't re-explain the company every time you hand them a task; their orientation is already loaded.
A Cog ≈ a configured stateless worker / microservice: a Lambda with an IAM role (governance) + env (frames) + a handler (the model). Spin up many, scale independently.
A Cog ≈ a named role on your team with a clear job description, scoped access, and an escalation policy — auditable as "what did this role do?" rather than "what did the AI do?"
A decorator wires the four parts together. Read it as: here is a worker, oriented by this Frame, allowed these tools, fenced by this governance.
@cog(
name="pr-review",
model="acme/code-review-7b", # may be fine-tuned/specialized
frames=["frame://acme/eng/payments@1.4"], # orientation (inherits the chain)
tools=["github.read_pr", "ci.status"],
governance=Governance(
may_read=["repo:payments/*"],
may_act=["post_review_comment"],
requires_human=["approve_merge"], # never auto-approves a merge
),
)
def review_pr(pr_url: str) -> Review:
... # the body is thin — the Frames + model do the cognitive work
The whitepaper's sharpest line: "A well-constructed Cog is, in large part, a well-managed context." At invocation, the Cog assembles a working context — Frames are the durable, governed foundation; everything else is assembled fresh around them. Order and constraints matter: Frames go first so everything downstream is oriented by them.
def assemble_context(cog: Cog, task: Task, memory: OrgMemory) -> Prompt:
"""Frames are the durable foundation; the rest is assembled per-invocation."""
return Prompt(
system = resolve(cog.frames), # 1. frames -> orientation
retrieved = memory.search(task.query, k=6), # 2. semantic recall (RAG)
history = memory.recent(cog, task.thread), # 3. conversation so far
tools = bind(cog.tools, gov=cog.governance),# 4. only permitted tools
task = task.instruction, # 5. the actual ask
)
This is exactly what the interactive panel below shows. The Cog is a pr-review worker. Toggle which Frames are active and watch the system context it would receive recompose in real time — color-coded by which Frame contributed each section, with overrides flagged where a more-specific Frame wins.
pr-review Cog
toggle Frames → watch the Cog's system context recompose
Because a Cog has a clear boundary, every run becomes a structured, queryable record. You stop asking "what did the model do?" and start asking "what did this Cog do, with what inputs, under which Frame versions, with what outcome?" — the difference between print() debugging and real distributed tracing. Cogs also compose: one can call sub-Cogs, just like a service calling other services.
# Every Cog run is a structured record written to Organizational Memory.
run = pr_review_cog.invoke(task)
audit.log(
cog="pr-review@1.2",
frames=run.frames_resolved, # the EXACT frame versions that oriented it
inputs=run.inputs,
actions=run.actions, # every tool call it made
outcome=run.outcome,
human_touchpoints=run.approvals,
)
# Cogs compose — a higher-level Cog delegates to specialist sub-Cogs:
notes = release_notes_cog.invoke(
task, sub_cogs=[changelog_cog, risk_summary_cog],
)
A Cog is a governed worker whose quality is mostly its context. The model is swappable; the value is the Frames that orient it, the tools it's allowed, and the boundary that makes it auditable. Build a Cog the way you'd provision a service — least privilege, clear inputs/outputs, traceable.
The installable, supervised workflow that maps onto how people describe their job.
An Op is the application of the whole architecture — the thing a human launches. "Cut the release." "Close the books." "Onboard this customer." "Qualify this lead." Each is an Op: one or more Cogs, plus Frames applied at the workflow level, a supervising model that sequences and parallelizes work, human-in-the-loop checkpoints, integration logic, and a Nebi manifest so it can be installed anywhere.
An Op is the runbook for a recurring process, except it executes. It calls the right specialists (Cogs) in the right order, runs some in parallel, pauses at the points where a human must approve or redirect, and only then takes the consequential action. It's a CI/CD pipeline with explicit human gates — and you can install it from a registry like any package.
An Op ≈ an Airflow DAG / Temporal workflow / CI pipeline — fan-out, fan-in, retries, approval gates — but packaged and installed like a pip package and adapted to each org by Frames.
An Op ≈ a documented business process turned into a one-click button. "Generate the quarterly board report" stops being a 12-step checklist in a wiki and becomes a launchable, auditable, repeatable unit.
One Cog, wrapped so it's launchable and carries workflow-level context:
@op(
name="triage-pr",
version="1.0.0",
frames=["frame://acme/proj/q3-release@0.9"], # workflow-level context
)
def triage_pr(pr_url: str) -> Review:
review = pr_review_cog.invoke(pr_url) # one Cog does the cognitive work
return review
Here's "cut the release" as an Op. It fans out three specialist Cogs in parallel, lets a supervising model decide whether to proceed, pauses for a human decision, and only acts after approval — with a loop-back path when the human asks for changes.
@op(name="cut-release", version="2.1.0",
frames=["frame://acme/proj/q3-release@0.9",
"frame://acme/legal/pci-dss@3.0"]) # frames at the workflow level
def cut_release(tag: str, ctx: OpContext):
# 1. fan out specialist Cogs IN PARALLEL — each carries its own frames
changelog, risks, compliance = ctx.parallel(
changelog_cog.task(tag),
risk_review_cog.task(tag), # PM lens: open blockers, owners, dates
compliance_cog.task(tag), # PCI lens: PAN logging, encryption
)
# 2. supervising model decides whether we may proceed
if compliance.has_violations or risks.has_blockers:
ctx.halt(reason=compliance.summary + risks.summary)
# 3. HUMAN-IN-THE-LOOP checkpoint — the release manager owns this call
decision = ctx.human_review(
title=f"Approve release {tag}?",
show=[changelog.draft, risks.table, compliance.report],
options=["approve", "refine", "abort"],
)
if decision != "approve":
return ctx.loop_back(decision) # refine -> re-run with feedback
# 4. act ONLY after human approval, then persist the whole run
publish_cog.invoke(tag, notes=changelog.draft)
ctx.memory.write(tag, changelog, risks, compliance, decision)
An Op ships with a Nebi manifest — think package.json for an AI workflow. It declares the Frames it needs by role rather than hard-coding them, which is the key to portability.
name: cut-release
version: 2.1.0
entrypoint: cut_release
requires:
cogs:
- changelog@^1.0
- risk-review@^2.0
- compliance@^3.0
frames: # declared by ROLE, not hard-coded — resolved on install
- role: compliance # "give me whatever compliance frame THIS hub has"
- role: release-policy
tools: [github, ci, slack]
triggers: [icon, cli, "cron: 0 9 * * 1"] # launcher | command | scheduled
human_checkpoints: [approve-release]
# Authored once. Installed into any compliant Hub via Nebi — like `pip install`.
$ nebi install op://openteams/cut-release@2.1.0
# The SAME Op behaves correctly in different orgs because it binds to LOCAL frames:
# Acme's Hub -> role:compliance resolves to PCI-DSS frame
# Mercy Health Hub -> role:compliance resolves to HIPAA frame
# One workflow, adapted to each organization's culture and law at install time.
An Op is an installable, versioned, human-supervised workflow. It's the package + the DAG + the approval gates, and it stays portable because it binds to the consuming org's Frames at install time instead of baking context in. Author once, run governed everywhere.
Follow a single request through the whole stack: "Ship the Q3 Payments release." A release manager clicks the cut-release Op icon in the Desktop Application. Here is everything that's now in play — and where each concept lives.
changelog, risk-review, and compliance run in parallel — each oriented by the resolved Frames, each fenced by its own governance.Mercy Health installs the same cut-release Op from the marketplace. Their Hub resolves role:compliance to a HIPAA Frame instead of PCI-DSS. The workflow is identical; the context, governance, and outcomes are wholly theirs. That's the thesis in one move: shared standards, sovereign context — author the work once, and every org runs it correctly under its own rules, on its own infrastructure, with its own data never leaving the building.
What to carry out of here when you onboard the next engineer or TPM:
| Concept | Role | Is | Is not |
|---|---|---|---|
| Frame | Context (data) | Versioned, inheritable, shareable org context — rules, terms, style, goals. | A throwaway prompt or a vendor's system message. |
| Cog | Worker | A model + Frames + tools + governance; the auditable unit of AI work. | An ungoverned "agent" blob; a bare model call. |
| Op | Orchestration | An installable, supervised workflow that runs Cogs with human gates. | A script with no checkpoints or no package boundary. |
| Nebi | Distribution | Packaging + reproducibility (pin, install, log). | A runtime or a model. |
| Hub | Deployment | The owned, governed environment it all runs in. | A shared multi-tenant SaaS you rent. |
Separation of concerns, one more time: Frame = what context/policy applies · Cog = who does one unit of work · Op = how work is coordinated and approved. Version, own, and reuse each independently — that's the entire point.