← 전체 글
AI와 에이전트 IT / CIO · · 작성자 ObjectStack Team

AI 모델은 기업에서 무엇이 부족한가? 세계, 손, 울타리

지능이 아니다. 기업에 들어온 모델에게는 추론할 세계, 행동할 손, 행동을 둘러싼 울타리가 없다. 실행 가능한 비즈니스 온톨로지 하나가 세 가지를 모두 공급하며, 출처를 단 표가 각각을 런타임 메커니즘에 대응시킨다.

AI 모델은 기업에서 무엇이 부족한가? 세계, 손, 울타리 AI 모델은 기업에서 무엇이 부족한가? 세계, 손, 울타리
  • AI 에이전트
  • 실행 가능한 비즈니스 온톨로지
  • MCP
  • 에이전트 권한

세계. 이 사업에 무엇이 존재하고, 각각이 어떤 타입이며, 서로 어떻게 연결되는가.

손. 에이전트가 그 세계에 수행해도 되는 작업. 호출할 수 있는 도구의 형태로 제공된다.

울타리. 누가 무엇을 해도 되는지를 한 번이 아니라 호출마다 판정하고, 사후에 기록하는 것.

AI 모델이 기업에 들어올 때 빠져 있는 것은 이 세 가지이고, 지능은 그 목록에 없다. 이 문장은 ObjectStack의 것으로, 그 첫 페이지의 “00 · The idea” 섹션을 위해 쓰였다. “What the model lacks is not intelligence: a world, hands, and a fence.”(모델에게 부족한 것은 지능이 아니다. 세계와 손과 울타리다.) 이 글은 그 뒤에 있는 더 좁고 검증 가능한 주장을 다룬다. 실행 가능한 비즈니스 온톨로지는 하나의 산출물에서 세 가지를 모두 공급하며, 각 공급은 소스에서 읽을 수 있는 이름 있는 런타임 메커니즘에 대응한다. 아래 표가 그 대응표이고, 모든 칸에 파일과 줄 번호를 달았다. 그 뒤에는 각 공급이 무엇인지, 번들된 CRM 예제에서 잰 숫자 하나, 가장 강한 대안을 공정하게 서술한 것, 그리고 이 중 무엇도 해결하지 못하는 것이 온다.

이 문장은 어디서 왔는가

2026-10-12부터 2026-10-27까지 objectstack.ai의 첫 페이지는 이 생각을 세 문장으로 진술했고, 페이지 소스는 그것을 글자 그대로 보존했다(이 섹션을 추가한 커밋 712361b7의 apps/docs/app/[lang]/page.tsx 127–131행. 세 문장 위의 주석에는 “verbatim from the maintainer’s ruling”, 즉 메인테이너의 결정을 그대로 옮겼다고 적혀 있다).

An enterprise is definition plus execution. When execution is nearly free, it is its definition.

What the model lacks is not intelligence: a world, hands, and a fence.

An ontology written clearly enough is software. Models change; the ontology stays.

(기업은 정의 더하기 실행이다. 실행이 거의 공짜가 되면, 기업은 곧 그 정의다. 모델에게 부족한 것은 지능이 아니다. 세계와 손과 울타리다. 충분히 명확하게 쓰인 온톨로지는 소프트웨어다. 모델은 바뀌고, 온톨로지는 남는다.)

출처에 관해 한 가지를 적어 둔다. 이 글의 다른 모든 출처는 태그가 붙은 하나의 릴리스에서 읽었기 때문이다. objectstack.ai를 개발자 사이트로 바꾼 개편(61c07986, 2026-10-27)이 이 섹션을 퇴역시켰고, 그래서 태그 @objectstack/[email protected]에서는 세 문장이 더 이상 저장소에 없다. 이 글의 나머지가 검증하는 생각은 여전히 같은 것이며, 그 검증은 이 문장이 어디에 인쇄되어 있는지에 달려 있지 않다.

가운데 문장을 진단으로 읽어 보라. 모든 기업 AI 파일럿은 유능한 모델을 회사에 연결하고 나서, 사고를 하나씩 겪으며 알게 된다. 모델은 이 회사에서 “거래처”가 무엇인지 몰랐다(세계가 없다). 실제로 하나를 바꿀 수 없었다(손이 없다). 건드리지 말았어야 할 것을 바꿨다(울타리가 없다). 흔한 대응은 빠진 조각을 각각 따로 사는 것이다. 세계를 위한 검색 계층, 손을 위한 함수 호출 계층, 울타리를 위한 정책 계층. 그것은 합리적인 대응이고, 이 글의 후반부는 그것에 마땅한 몫을 준다. 첫째와 셋째 문장은 ObjectStack이 왜 다른 길을 택하는지를 말한다. 사업의 정의가 실행될 만큼 정확하게 쓰여 있다면, 바로 그 정의가 세계이고, 손을 선언하고, 울타리를 지니며, 이번 분기에 그것을 읽는 모델이 무엇이든 그보다 오래 살아남는다.

세 가지 공급, 하나의 산출물

ObjectStack README의 한 줄 정의는 “실행 가능한 비즈니스 온톨로지 하나. AI가 쓰고, 런타임이 실행하고, 에이전트가 운영하고, 당신이 소유합니다.”이다. 개념 페이지는 그 핵심을 여섯 종류의 것으로 나열한다. 오브젝트와 필드, 관계, 액션, 권한, 플로우, 그리고 에이전트와 도구 정의. 이 글의 주장은 그 여섯 종류가 세 가지 공급으로 나뉘고, 런타임이 각각을 누군가 접착 코드를 쓰지 않아도 에이전트가 쓸 수 있는 것으로 바꾼다는 것이다. 대응표는 다음과 같다. 모든 출처는 태그 @objectstack/[email protected](2026-11-04 읽음, 그날 npm create objectstack@latest가 설치하는 릴리스)의 objectstack-ai/objectstack 파일이거나, 같은 저장소에서 빌드되는 그 문서의 페이지다.

모델에게 부족한 것온톨로지 안에서 그것을 공급하는 것런타임 메커니즘, 그리고 그것이 쓰인 곳
세계 — 명사: 어떤 엔티티가 존재하고, 각각 어떤 타입이며, 어떻게 관계되는가오브젝트와 필드; 관계(여섯 종류 중 둘)타입이 있는 정의 하나가 objectstack.json으로 컴파일된다. 런타임은 거기서 데이터베이스 스키마, REST와 실시간 API, Console UI, MCP 서버를 도출한다(ontology.mdx:64-70). 에이전트는 그 세계를 list_objects와 describe_object로 읽는다(connect-mcp.mdx:225-229).
손 — 동사: 그 명사들에 무엇을 해도 되는가액션, 플로우, 그리고 레코드 자체실행 중인 앱은 /api/v1/mcp의 MCP 서버이며 기본으로 켜져 있다. 오브젝트는 자동으로 노출되고, 액션은 ai: { exposed: true }로 옵트인한다(README.md:136-151). 이 옵트인은 기본값이 false인 스키마 필드이며, 40자 이상의 LLM용 설명을 요구한다(action.zod.ts:815-822).
울타리 — 누가 어떤 행과 어떤 필드에 무엇을 해도 되는지, 호출마다 확인하고 기록한다권한, 행 수준과 필드 수준 보안, 공유, 감사보안은 ObjectQL 엔진에 등록된 미들웨어이므로 엔진의 모든 작업이 그것을 거친다(security-plugin-authz-middleware.ts:4-7). MCP 도구는 호출자의 주체로, “the SAME permission/RLS-enforcing path the REST API uses”(REST API가 쓰는 것과 동일한 권한/RLS 강제 경로)를 통해 실행된다(mcp-http-tools.ts:7-11). 감사 행은 모든 삽입, 갱신, 삭제에서 엔진 훅이 기록한다(audit-writers.ts:2435-2440).

인용을 열어 볼 수 있도록 파일 위치를 적는다. README.md는 저장소 루트; ontology.mdx는 content/docs/concepts/, connect-mcp.mdx는 content/docs/ai/; action.zod.ts는 packages/spec/src/ui/; security-plugin-authz-middleware.ts는 packages/plugins/plugin-security/src/; mcp-http-tools.ts는 packages/mcp/src/; audit-writers.ts는 packages/plugins/plugin-audit/src/. 줄 번호는 이 태그의 것이다.

개념 페이지는 오른쪽 열을 한 문장으로 압축하는데, 통째로 옮길 가치가 있다. 런타임은 “enforces the definition on every call. RBAC, row-level and field-level security, sharing, and audit apply to a REST request, a Console click and an agent’s tool call alike. Nothing is reasoned over at runtime: what runs is what was validated.”(모든 호출에서 정의를 강제한다. RBAC, 행 수준과 필드 수준 보안, 공유, 감사는 REST 요청, Console 클릭, 에이전트의 도구 호출에 똑같이 적용된다. 런타임에서 추론되는 것은 없다. 실행되는 것은 검증된 것이다.)

objectstack.config.ts에서 objectstack.json으로 컴파일된 실행 가능한 비즈니스 온톨로지 하나가 세 가지를 공급한다. 세계(오브젝트, 필드, 관계. 런타임은 거기서 데이터베이스, API, describe_object 도구를 도출한다), 손(ai exposed true로 옵트인한 액션, 플로우, 레코드. /api/v1/mcp에서 MCP 도구로 제공된다), 울타리(권한 세트, 행 수준과 필드 수준 보안, 공유, 감사. 모든 엔진 호출에서 보안 미들웨어가 강제하고 감사 훅이 기록한다)

이제 표의 세 행을 차례로 짚는다.

세계: 런타임도 읽는 정의

모델의 세계는 두 독자를 동시에 만족시켜야 한다. 모델에게는 통째로 담을 수 있을 만큼 작고 명시적이어야 하고, 런타임에게는 실행할 수 있을 만큼 정확해야 한다. 문서는 첫째 독자를 만족시키고 둘째는 만족시키지 못한다. 검색해 온 정책 PDF는 모델에게 영업 기회가 무엇인지 알려 주지만, 데이터베이스가 거기에 동의하는지는 아무것도 확인하지 않는다.

실행 가능한 온톨로지의 세계는 타입이 있는 정의 그 자체다. 개념 페이지에 따르면 온톨로지는 “is the definition of your business that the runtime executes: authored as typed metadata in objectstack.config.ts, compiled into the objectstack.json artifact.”(런타임이 실행하는 당신 사업의 정의다. objectstack.config.ts에 타입이 있는 메타데이터로 작성되고, objectstack.json 산출물로 컴파일된다.) 오브젝트와 필드는 엔티티와 그 타입이 있는 속성을 선언하고, 관계는 조회와 마스터-디테일 연결을 선언한다. 런타임은 그 정의에서 테이블과 엔드포인트를 도출하고, MCP 서버의 describe_object 도구도 같은 정의에서 답한다. 그래서 에이전트가 읽는 세계는 구성상 실행되는 세계와 같다. 어긋날 두 번째 서술이 없다.

두 가지 귀결이 따르며, 둘 다 이 블로그에서 이미 논증되었으므로 반복하지 않고 가리키기만 한다. 첫째, 세계에는 경계가 있다. 뷰, 대시보드, 앱, 번역은 온톨로지의 투영이지 그 일부가 아니며, 이것이 에이전트가 모든 화면이 아니라 핵심에서 출발해 사업을 추론할 수 있게 한다(정의 글에 둘을 구별하는 제거 테스트가 있다). 둘째, 세계는 실행되기 전에 검증된다. os validate는 타입 검사는 통과하지만 런타임에서 조용히 실패할 정의를, 빠진 보안 자세까지 포함해 거부한다. 그래서 에이전트에게 건네지는 세계는 그 안의 모든 매달린 참조에 대해 이미 한 번씩 거부를 거쳤다.

손: 모델이 추측한 도구가 아니라 작성자가 무장시킨 도구

손은 대부분의 기업 AI 스택이 함수 호출의 형태로 이미 가진 부분이다. 실행 가능한 온톨로지가 만드는 차이는 어떤 손이 존재하는지를 누가 정하느냐에 있다.

오브젝트에는 기본으로 손이 딸려 온다. 정의가 타입이 있으므로 런타임은 그것을 MCP 서버로 제공한다. “Objects are tools, actions are tools, permissions decide what an agent may call, and audit records what it did”(오브젝트는 도구이고, 액션은 도구이며, 권한이 에이전트가 무엇을 호출해도 되는지 정하고, 감사가 그것이 무엇을 했는지 기록한다)(README.md:138-139). connect-mcp 페이지는 에이전트가 얻는 것을 “Twelve tools, generated from your metadata”(당신의 메타데이터에서 생성된 열두 개의 도구)로 나열한다. 발견(list_objects, describe_object, validate_expression), 읽기(query_records, get_record, aggregate_records), 쓰기(create_record, update_record, delete_record), 그리고 액션(list_actions, run_action, resume_run). 새 오브젝트를 위해 도구 정의를 쓰는 사람은 없다. 오브젝트가 곧 도구다.

액션에는 기본으로 손이 딸려 오지 않으며, 이것이 의도된 부분이다. 액션은 작성자가 ai: { exposed: true }를 설정하고 모델이 그것을 고를 근거가 될 설명을 쓸 때에만 에이전트가 호출할 수 있게 된다. action.zod.ts의 스키마 주석이 그 이유를 말한다. “This is a deliberate governance gate: in an AI-authoring world the platform’s value is that a human can govern exactly which capabilities the agent fleet is allowed to invoke — a half-finished or unreviewed action must never be silently armed.”(이것은 의도적인 거버넌스 게이트다. AI가 작성하는 세계에서 플랫폼의 가치는, 에이전트 집단이 어떤 기능을 호출해도 되는지를 사람이 정확히 통제할 수 있다는 데 있다. 반쯤 만들어졌거나 검토되지 않은 액션이 조용히 무장되는 일은 결코 있어서는 안 된다.) 가장 작은 번들 예제인 todo 앱은 이렇게 하나를 무장시킨다(examples/app-todo/src/actions/task.actions.ts, UI 전용 키는 덜어냈다).

export const CompleteTaskAction = defineAction({
  name: 'complete_task',
  label: 'Mark Complete',
  objectName: 'todo_task',
  type: 'script',
  target: 'completeTask',
  ai: {
    exposed: true,
    description: 'Mark a todo task as complete. Use when the user says a task is done or finished.',
  },
});

반면 번들된 CRM은 하나도 무장시키지 않는다. 유일한 액션인 Convert Lead는 ai 블록이 없는 flow 액션이어서, 이 앱에 연결된 에이전트는 여섯 오브젝트에 대한 모든 데이터 도구를 가지면서도 list_actions에서는 빈 답을 받는다. 이것은 예제의 빈틈이 아니라 규칙이 작동하는 모습이다. 비즈니스 로직에 대한 손은 정의 안의 검토된 한 줄로 부여되는 것이지, 버튼이 존재한다는 사실에서 가정되는 것이 아니다.

왜 하필 쓰기 작업이 UI 옆에 두 번째 도구 경로를 두는 대신 이 하나의 통제된 정의를 필요로 하는지는 온톨로지 액션 글의 주제이므로 여기서 반복하지 않는다.

울타리: 런타임이 호출마다 판정한다

프롬프트 안에 사는 울타리는 부탁이다. 도구 앞의 정책 서비스 안에 사는 울타리는 호출에 대한 관문이다. 실행 가능한 온톨로지가 지닌 울타리는 데이터 경로 자체 위에 있으며, 이 차이가 하나의 실수가 어디까지 닿을 수 있는지를 결정한다.

메커니즘은 미들웨어다. plugin-security는 그 강제를 ObjectQL 엔진에 등록하고(ql.registerMiddleware(...), security-plugin-authz-middleware.ts:2466, 플러그인의 start()에서 실행된다), 엔진은 요청이 REST 라우트에서 왔든, Console 클릭에서 왔든, MCP 도구에서 왔든 모든 읽기와 쓰기가 거치는 곳이다. MCP 도구 모듈은 자기 헤더에서 데이터 엔진을 직접 건드리지 않는다고 말한다. “all reads/writes go through an injected McpDataBridge that the host wires to the SAME permission/RLS-enforcing path the REST API uses. This module owns the tool shape; the bridge owns execution + security.”(모든 읽기/쓰기는 주입된 McpDataBridge를 거치며, 호스트는 그것을 REST API가 쓰는 것과 동일한 권한/RLS 강제 경로에 연결한다. 이 모듈은 도구의 형태를 소유하고, 브리지는 실행과 보안을 소유한다.) 사람용 울타리와 동기화를 유지해야 할 에이전트 전용 울타리는 없다. 울타리가 하나뿐이기 때문이다. 각 검사가 정확히 어디에서 실행되는지, 그리고 왜 모델의 출력을 사후에 거르는 것은 너무 늦은지는 에이전트 권한은 어디에서 강제되는가에서 논증한다.

이 울타리의 세 가지 성질은 이름 붙일 가치가 있다. 대안 스택은 보통 그중 적어도 하나가 없기 때문이다.

호출만이 아니라 행과 필드에 대해 판정한다. 권한 세트는 오브젝트 수준의 생성, 읽기, 편집, 삭제를 부여하고, 행 수준 보안은 호출자가 볼 수 있는 레코드를 거르며, 필드 수준 보안은 어떤 열을 가릴지 정한다. 보안 서비스 계약은 행 필터의 실패 자세를 분명히 적는다. “Access-narrowing answers fail CLOSED … a resolution failure returns a DENY filter (zero rows), never undefined”(접근을 좁히는 답은 실패 시 닫힌다…… 해석 실패는 DENY 필터(0행)를 돌려주며, 결코 undefined를 돌려주지 않는다)(packages/spec/src/contracts/security-service.ts:28-31). 모든 것을 요구하는 모델이 받는 것은 그 사용자가 봐도 되는 것이다.

비즈니스 로직은 따로 관문을 둔다. 로직에는 뒷받침이 없기 때문이다. 오브젝트 CRUD는 모든 행에서 RLS와 FLS에 둘러싸여 있다. 액션 본문은 그렇지 않다. 일단 호출되면 그것은 “executes as TRUSTED app code,”(신뢰된 앱 코드로 실행되므로) 브리지는 “gates at invoke time: ai.exposed (the author’s explicit AI opt-in, ADR-0011) + the ADR-0066 D4 capability gate”(호출 시점에 관문을 둔다. ai.exposed(작성자의 명시적 AI 옵트인, ADR-0011)와 ADR-0066 D4 기능 게이트로)(mcp-http-tools.ts:1450-1455). 손과 울타리는 바로 여기서 만난다. 액션을 무장시키는 그 한 줄이 울타리가 확인하는 한 줄이다.

기록한다. 감사 기록기는 afterInsert, afterUpdate, afterDelete의 엔진 훅이어서(audit-writers.ts:2435-2440), 에이전트의 update_record로 바뀐 행은 Console에서 바뀐 행과 같은 방식으로, 행위자 신원과 함께 감사 로그에 남는다. README의 네 번째 게이트는 그 귀결을 한 줄로 적는다. “The runtime enforces permissions and audit on every call, so even a wrong app stays inside the fence.”(런타임은 모든 호출에서 권한과 감사를 강제하므로, 잘못된 앱조차 울타리 안에 머문다.)

번들된 CRM에서 잰 숫자

숫자 하나. 태그 @objectstack/[email protected]의 examples/app-crm에서, README가 이 앱을 세는 방식(src/ 아래 TypeScript, 테스트 제외)으로 쟀다. README 자신의 숫자인 1,873줄은 그보다 앞선 커밋(95294be3) 기준이다. 그 뒤로 앱이 늘린 213줄 가운데 178줄이 번역이다.

find examples/app-crm/src -name '*.ts' -not -name '*.test.ts' | xargs cat | wc -l
# 2086

30개 파일에 걸친 2,086줄이 애플리케이션 전체다. 그 디렉터리를 세 가지 공급으로 나누면:

공급디렉터리줄 수들어 있는 것
세계src/objects/516여섯 오브젝트(거래처, 연락처, 리드, 영업 기회, 영업 기회 품목, 활동)와 그 필드 및 조회
손src/actions/ + src/flows/240액션 하나, Convert Lead와 그것이 시작하는 화면 플로우
울타리src/security/99그중 sales-positions.ts가 89줄: 권한 세트 둘, 직위 셋. 각 직위는 자신이 배포하는 세트를 명시한다
배관도구 등록, 인가 미들웨어, 감사 코드0src/ 전체에서 registerTool, middleware, authoriz, checkPermission, audit를 검색하면 네 건이 나오며 모두 주석 안이다

나머지는 투영(뷰, 대시보드 하나, 앱 하나, 페이지 하나, 번역, 분석 데이터셋 하나)과 시드 데이터로, 이 글의 주제가 아니다.

머리 숫자를 울타리 89줄이라고 부르자. 그것이 여섯 오브젝트 CRM의 인가 선언 전체이며, 같은 89줄이 REST API, Console, 열두 개의 MCP 도구 전부를 다스린다. 셋 모두 울타리가 장착된 엔진을 통해 데이터에 닿기 때문이다. 보완하는 숫자는 0이다. 애플리케이션은 자기 세계, 손, 울타리를 선언하지만, 그것들을 모델에 연결하는 코드는 한 줄도 담고 있지 않다. 배선은 런타임의 몫이고, 그것이 “하나의 산출물”이라는 말의 내용 전부다.

측정에 관해 정직한 각주 둘. 89줄은 앱 자신의 선언이고, 그것이 함의하는 행 필터와 필드 가림은 런타임이 각 오브젝트의 sharingModel과 그 권한 세트들로부터 계산한다. 그래서 실행 중인 시스템의 “울타리”는 그 선언보다 크며, 마땅히 그래야 한다. 그리고 위에서 말했듯 이 CRM은 AI에 액션을 하나도 노출하지 않으므로, 작성자가 하나를 무장시키기 전까지 비즈니스 로직에 대한 손은 0이다.

대안을 공정하게 말하면

세 가지를 공급하는 흔한 방법은 스택이다. 세계를 위해 문서와 스키마에 대한 검색, 손을 위해 함수 호출(또는 직접 쓰는 도구 서버), 울타리를 위해 도구 앞의 정책 엔진이나 게이트웨이. 이것은 공정한 청문을 받을 자격이 있다. 여러 상황에서 그것이 정답이기 때문이다.

이미 운영 중인 시스템과 함께 작동한다. 아무것도 이전하지 않는다. 검색기는 존재하는 것을 색인하고, 도구는 이미 있는 API를 감싼다. 각 계층은 최고의 것으로 고르고 교체할 수 있어서, 더 나은 검색기나 더 엄격한 정책 엔진을 다른 계층을 건드리지 않고 끼울 수 있다. 패턴은 잘 알려져 있고, 벤더는 많으며, 이미 도구 게이트웨이를 가진 팀은 울타리의 대부분을 갖춘 셈이다. 십여 개의 레거시 시스템을 가로질러 읽고 어디에도 쓰지 않는 것이 일인 에이전트라면 이 스택이 아마 원하는 것이고, 그 시스템들 위의 실행 가능한 온톨로지는 읽기 전용이며 아직 초기다.

그것이 해결하지 못하는 것은 첫 페이지의 첫 문장이 말하는 것이다. 세 가지 공급이 세 개의 산출물이고, 주인이 셋이며, 그것들이 일치하는지 확인하는 것이 아무것도 없다.

RAG + 함수 호출 + 정책 계층실행 가능한 온톨로지 하나
세계모델이 읽는 말뭉치; 시스템은 그것을 읽지 않는다런타임이 실행하는 정의; describe_object가 거기서 답한다
손손으로 쓴 도구 스키마, 작업마다 하나, 시스템 옆에서 따로 유지오브젝트는 자동으로 도구; 액션은 검토된 한 줄로 옵트인
울타리도구 호출에 대한 관문, 보통 각 도구 뒤에 서비스 계정의 권한데이터 경로 위의 미들웨어, 호출한 사용자의 권한으로, 행과 필드까지 포함
드리프트사업에 대한 세 가지 서술, 각각이 낡을 수 있다하나의 산출물, 실행 전에 검증됨
감사호출은 기록된다; 행 변경은 하류 시스템의 문제행 변경이 신원과 함께, 모든 경로에서 기록된다

사고가 났을 때 가장 중요한 것은 울타리 행이다. get_customer 도구 앞의 정책 계층은 에이전트가 그것을 호출해도 되는지 결정할 수 있다. 결과 안의 어떤 행을 에이전트의 사용자가 봐도 되는지는 보통 결정하지 못한다. 도구는 통합에 주어진 자격 증명이 무엇이든 그것으로 실행되기 때문이다. 데이터 경로 위의 행 수준과 필드 수준 보안은 모든 호출자에 대해 그 질문에 답하며, 사람과 에이전트에게 같은 답을 준다.

이것이 해결하지 못하는 것

울타리에 관한 글은 울타리가 어디서 끝나는지 말해야 한다.

판단을 공급하지 않는다. 울타리는 잘못된 호출을 거부 가능하고 추적 가능하게 만들지만, 그 호출을 옳게 만들지는 않는다. 모델은 여전히 잘못된 도구를 고르고, 필드를 잘못 읽고, 원하지 말았어야 할 액션을 요청할 수 있다. 세계와 울타리는 피해를 한정한다. 지능, 즉 모델이 실제로 가져오는 그것이 여전히 선택을 한다.

옵트인 게이트는 런타임이 소유한 문을 지킨다. ai.exposed 게이트는 MCP run_action 도구에서 닿는 액션 문에서 강제된다. 스펙 자신의 주석은 명시적이다. “REST /actions is NOT ai.exposed-gated and sits OUTSIDE this gate, so a human in front of that route is still yours to arrange”(REST /actions는 ai.exposed로 관문이 쳐져 있지 않고 이 게이트 바깥에 있으므로, 그 라우트 앞에 사람을 둘지는 여전히 당신이 마련할 일이다)(packages/spec/src/ai/tool.zod.ts:95-98). 그 라우트에서도 권한은 적용된다. AI 옵트인은 적용되지 않는다.

읽기 감사는 쓰기 감사보다 좁다. 모든 삽입, 갱신, 삭제가 기록된다. 레코드 상세 조회를 기록하는 것은 오브젝트별 옵트인이며, 목록과 검색 결과는 감사되지 않는다(packages/plugins/plugin-audit/src/audit-plugin.ts:49-68). 널리 읽는 에이전트는 쓰는 에이전트보다 작은 흔적을 남긴다.

세계는 런타임이 실행하는 앱이다. 런타임이 실행하지 않는 시스템에 대해서는, 외부 데이터소스 연합이 기본적으로 읽기 전용이며 초기 단계로 설명된다. 세 가지 공급은 온톨로지가 실행하는 것을 덮고, 나머지 자산에는 여전히 위의 스택이나 이전이 필요하다.

노출된 액션은 신뢰된 코드다. run_action 도구는 자기 설명에서 모델에게 그렇게 말한다. 액션 본문은 “runs as trusted application code with the app’s full data authority.”(앱의 전체 데이터 권한을 가진 신뢰된 애플리케이션 코드로 실행된다.) 그러므로 액션을 무장시키는 것은 토글이 아니라 검토 결정이며, 먼저 사람에게 물어야 할 것들을 위해 requiresConfirmation: true가 있다.

호스팅으로, 또는 자체 인프라에서

위의 모든 것은 개방 스택이고, Apache-2.0이며, 하나의 저장소에 있다. 정의는 당신 손에 있는 파일이다. 이를 실행하기 위해 ObjectStack 저장소는 ObjectOS Community(ghcr.io/objectstack-ai/objectstack 이미지, os start, Console로 이루어진 무료 직접 호스팅 에디션)를 제공하며, ObjectOS Cloud는 호스팅 에디션, ObjectOS Enterprise는 직접 운영하는 라이선스 에디션입니다. (태그 시점 README의 문장 README.md:26-31을 옮긴 것이다.) ObjectOS는 세 가지 에디션으로 제공됩니다. 오픈소스이며 무료로 직접 호스팅하는 ObjectOS Community, 설치 없이 브라우저에서 호스팅되는 ObjectOS Cloud, 자체 인프라에서 직접 운영하는 ObjectOS Enterprise입니다. 온톨로지는 일반적인 ObjectStack 메타데이터입니다. ObjectOS Cloud 또는 ObjectOS Enterprise에서 내보내 오픈소스 ObjectStack 런타임에서 실행하는 기능은 계획 중입니다. 세 가지 공급은 그 메타데이터의 일부이므로, 어느 에디션이 실행하든 그대로 성립한다.

당신의 에이전트를 여기로 향하게 하라

위 대응표를 믿음으로 받아들일 필요는 없다. 실행 중인 앱이 어떤 MCP 클라이언트에게든 그것을 보여 준다.

  1. npm create objectstack@latest my-app으로 프로젝트를 만든다. 스캐폴더가 AGENTS.md를 쓰고 스킬 번들을 설치하므로, 코딩 에이전트는 프로토콜의 규칙을 읽어 들인 채 시작한다. 에이전트를 ObjectStack으로 향하게 하는 법이 규칙 파일과 도구 서버를 다룬다.
  2. 에이전트에게 세계를 요청한다. 필드가 있는 오브젝트 몇 개와 그 사이의 조회 하나. npm run validate를 실행하게 하고, Console보다 먼저 diff를 읽는다.
  3. npx os dev --ui로 앱을 시작하고 아무 MCP 클라이언트나 http://localhost:3000/api/v1/mcp로 향하게 한다. 에이전트는 사용자로서, 배포 자체의 OAuth 서버나 API 키를 통해 연결하고, describe_object는 방금 검토한 세계를 돌려준다.
  4. 손 하나를 무장시킨다. 액션 하나에 설명과 함께 ai: { exposed: true }를 주고, 다시 검증하고, list_actions가 빈 것에서 하나로 바뀌는 것을 본다.
  5. 첫 사용자가 가진 권한이 없는 두 번째 사용자로 울타리를 시험하고, 거부와 감사 행을 읽는다.

Connect an MCP Client 페이지에는 모든 클라이언트의 한 줄 명령이 있고, Business Ontology 페이지는 정의 자체의 권위 있는 출처다. 둘 다 에이전트에게 건네라. 세계, 손, 울타리는 에이전트가 이제 막 쓰려는 같은 파일 안에 있다.