[{"data":1,"prerenderedAt":3735},["ShallowReactive",2],{"docs-nav":3,"docs-article-engineering\u002Fsystem-design\u002Fagentic-platform\u002Fcontract":797},[4,17,27,44,55,67,75,82,94,106,114,122,129,135,144,153,161,169,177,189,202,211,218,229,240,248,260,268,276,286,296,305,314,323,331,337,343,350,356,364,371,378,383,393,401,410,415,422,432,439,444,451,458,462,467,475,487,499,509,516,525,533,539,545,551,557,563,567,579,593,603,614,621,626,633,640,646,653,658,665,673,678,686,692,699,704,710,721,730,740,747,753,761,767,776,782,791],{"path":5,"title":6,"description":7,"group":8,"section":6,"order":9,"tags":10,"lastUpdated":16},"\u002Fagents\u002Fagentic-crm","Agentic CRM","Research brief and build plan for an AgencyCore agentic CRM layer, rendered as an interactive page — the core operating loop, the target architecture, the typed-tool risk gateway, the proposed-actions review queue, and the four-slice MVP.","Agents",0,[11,12,13,14,15],"crm","agents","ai","architecture","research","2026-06-12",{"path":18,"title":19,"description":20,"group":8,"section":21,"order":22,"tags":23,"lastUpdated":26},"\u002Fagents\u002Fchat","Chat agent","High-level system design of the AgencyCore chat agent — core components, data flow, and the two abstractions that hold it together.","Reference",1,[12,14,24,25],"chat","system-design","2026-05-13",{"path":28,"title":29,"description":30,"group":8,"section":31,"order":32,"tags":33,"lastUpdated":43},"\u002Fagents\u002Fcompany-enrichment","Company Enrichment","The company enrichment workflow - a cache-first read in front of the company intelligence database that fills firmographic, contact and technographic facts via a fixed-order provider waterfall, and writes every resolved fact back with provenance so the first org pays once and every later search rides free.","Enrichment",2,[12,34,35,36,37,38,39,40,41,42],"workflow","enrichment","companies","waterfall","cache","intelligence-database","firmographics","provenance","sonar","2026-06-10",{"path":45,"title":46,"description":47,"group":8,"section":48,"order":9,"tags":49,"lastUpdated":54},"\u002Fagents\u002Fcompany-sonar","Company Signals","Signal-first company discovery for marketing agencies, on the Claude Agent SDK, with a global intelligence cache and deterministic composite scoring.","Company Sonar",[12,34,42,50,51,52,35,53,14],"company-search","signals","agent-sdk","scoring","2026-06-08",{"path":56,"title":57,"description":58,"group":8,"section":48,"order":22,"tags":59,"lastUpdated":66},"\u002Fagents\u002Fcompany-sonar\u002Fsignal-monitoring","Company Signals Monitoring","Realtime signal capture layer on top of the data graph. Detects hot events, scores them with a Claude managed agent against each agency's ICP, fans out alerts.",[14,51,60,61,62,63,64,65],"intel","icp","alerts","monitoring","sse","managed-agents","2026-06-09",{"path":68,"title":69,"description":70,"group":8,"section":71,"order":22,"tags":72,"lastUpdated":74},"\u002Fagents\u002Fconcepts\u002Fchat-agent-design-principles","Designing chat agents","The 2026 playbook for production chat agents that reach into internal systems via tools — context engineering, memory, tool design, when to add complexity.","Concepts",[12,14,24,73],"context-engineering","2026-05-14",{"path":76,"title":77,"description":78,"group":8,"section":71,"order":32,"tags":79,"lastUpdated":74},"\u002Fagents\u002Fconcepts\u002Fsystem-prompt-architecture","System prompt architecture","How to structure a production chat agent system prompt — eight sections, what each one does, and the rules vendors converge on.",[12,80,81],"prompt-engineering","system-prompt",{"path":83,"title":84,"description":85,"group":8,"section":84,"order":9,"tags":86,"lastUpdated":54},"\u002Fagents\u002Fenvoy","Envoy","High-level system design for the AI outreach engine — the sequence step state machine, the human-in-the-loop draft approval gate, multi-source context enrichment, and the inbox sentiment flow, rendered as an interactive page.",[12,87,88,89,90,91,92,93,14],"envoy","outreach","sales-engagement","sequences","state-machine","human-in-the-loop","nylas",{"path":95,"title":96,"description":97,"group":8,"section":98,"order":9,"tags":99,"lastUpdated":16},"\u002Fagents\u002Fheadhunter","Headhunter","The AI talent-search pipeline on one page - the production six-step design with its current-title relevance gate, and the 2.0 system design with internal-first waterfall sourcing, a pluggable source registry, automatic entity resolution, and a people intelligence graph that compounds every run.","General Search",[12,34,100,101,14,25,102,37,103,104,105],"headhunter","recruiting","multi-source","entity-resolution","people-intelligence","flywheel",{"path":107,"title":108,"description":109,"group":8,"section":21,"order":32,"tags":110,"lastUpdated":113},"\u002Fagents\u002Fpaperclip","Paperclip","Architecture deep dive into the Paperclip orchestration system.",[12,14,111,112],"orchestration","paperclip","2026-04-20",{"path":115,"title":116,"description":117,"group":8,"section":31,"order":22,"tags":118,"lastUpdated":16},"\u002Fagents\u002Fpeople-enrichment","People Enrichment","The people enrichment workflow - a cache-first read in front of the people intelligence database that fills profile, contact and employment facts via a fixed-order provider waterfall, keyed on the LinkedIn URL, and writes every resolved fact back with provenance so the first org pays once and every later search rides free. The fill step Headhunter and People Signals both call.",[12,34,35,119,37,38,39,120,41,100,121],"people","linkedin","people-sonar",{"path":123,"title":124,"description":125,"group":8,"section":126,"order":9,"tags":127,"lastUpdated":54},"\u002Fagents\u002Fpeople-sonar","People Signals","Signal-first people discovery for marketing agencies, built on the headhunter pipeline, with a composite score weighted by signal strength, source reputation, recency, and ICP fit.","People Sonar",[12,34,121,128,51,100,35,53,14],"people-search",{"path":130,"title":131,"description":132,"group":8,"section":126,"order":22,"tags":133,"lastUpdated":54},"\u002Fagents\u002Fpeople-sonar\u002Fpeople-signal-monitoring","People Signals Monitoring","Forward-looking design for the push layer that tracks known people - champions, past contacts, target-company decision-makers - and fires a warm lead the moment they change jobs, get promoted, or their company has an event.",[14,51,60,119,63,134],"warm-leads",{"path":136,"title":137,"description":138,"group":139,"section":140,"order":22,"tags":141,"lastUpdated":143},"\u002Fengineering\u002Fguides\u002Fagent-execution-stack","The Agent Execution Stack","Durable workflows over pluggable agent backends — how AgencyCore runs AI agents on Inngest over a webhook-driven Claude Managed Agents backend.","Engineering","Guides",[12,142,14,25],"inngest","2026-06-25",{"path":145,"title":146,"description":147,"group":139,"section":140,"order":9,"tags":148,"lastUpdated":143},"\u002Fengineering\u002Fguides\u002Fagent-runtime","Agent runtime","How AgencyCore runs AI agents on a provider-neutral runtime — the abstraction layer that lets us swap the agent backend, with Claude managed agents as the current provider.",[12,149,14,150,151,152,25],"runtime","anthropic","claude","providers",{"path":154,"title":155,"description":156,"group":139,"section":21,"order":157,"tags":158,"lastUpdated":160},"\u002Fengineering\u002Freference\u002Fagno-to-agent-sdk-migration","Agno → Claude Agent SDK migration","System-design spec for moving the ac-python-api workflow engine off Agno onto Anthropic's Claude Agent SDK \u002F Managed Agents, tiered by control-flow shape.",10,[12,14,159,52,65],"migration","2026-06-06",{"path":162,"title":163,"description":164,"group":139,"section":21,"order":22,"tags":165,"lastUpdated":54},"\u002Fengineering\u002Freference\u002Fcloudflare-agent-sandbox","Cloudflare agent sandbox","Cloudflare's Workers-based agent platform, evaluated as an alternative sandbox for our Agno workflows.",[12,166,167,168,159],"sandbox","cloudflare","workers",{"path":170,"title":171,"description":172,"group":139,"section":21,"order":32,"tags":173,"lastUpdated":176},"\u002Fengineering\u002Freference\u002Fvirtual-filesystem-rag","Virtual filesystem for AI assistants","How ChromaFs provides AI agents with structured file access.",[12,174,14,175],"rag","chromafs","2026-04-18",{"path":178,"title":179,"description":180,"group":139,"section":181,"order":182,"tags":183,"lastUpdated":188},"\u002Fengineering\u002Fsystem-design\u002Fagentic-platform\u002Fcapabilities\u002Fstate-and-knowledge","State and knowledge","What a run may know. One deterministic context builder over application state, knowledge and memory, one owner for every fact, and memory that is written through a tool.","Agentic platform",11,[184,185,186,11,187],"context","memory","knowledge","pgvector","2026-08-31",{"path":190,"title":191,"description":192,"group":139,"section":181,"order":157,"tags":193,"lastUpdated":201},"\u002Fengineering\u002Fsystem-design\u002Fagentic-platform\u002Fcapabilities\u002Ftools-and-integrations","Tools and integrations","A tool is the one way an agent reaches the world. AgencyCore owns the model facing contract, the invoke path, the credentials and the result boundary.",[194,195,196,197,198,199,200],"tools","integrations","mcp","agno","policy","security","idempotency","2026-09-04",{"path":203,"title":204,"description":205,"group":139,"section":181,"order":22,"tags":206,"lastUpdated":210},"\u002Fengineering\u002Fsystem-design\u002Fagentic-platform\u002Fcontract","Platform contract","One platform behind chat, interactive channels, triggers, approvals and background runs, with one Agno runtime, one tool layer, one state layer, and three cross-cutting planes.",[12,14,197,142,194,207,149,208,198,209],"skills","channels","observability","2026-09-02",{"path":212,"title":181,"description":213,"group":139,"section":214,"order":22,"tags":215,"lastUpdated":201},"\u002Fengineering\u002Fsystem-design\u002Fagentic-platform","The whole agentic platform on one page - who starts a run, the one boundary every run passes, how the work executes, and what comes back.","System design",[12,14,216,197,142,217,198],"overview","runs",{"path":219,"title":220,"description":221,"group":139,"section":181,"order":222,"tags":223,"lastUpdated":228},"\u002Fengineering\u002Fsystem-design\u002Fagentic-platform\u002Finterfaces\u002Fagent-access","Agent access (CLI and MCP)","How an outside AI agent reaches AgencyCore. The ac CLI works today as a user seat. An MCP server is planned and not designed.",6,[224,196,12,151,225,226,227],"cli","access","auth","todo","2026-08-18",{"path":230,"title":231,"description":232,"group":139,"section":181,"order":233,"tags":234,"lastUpdated":239},"\u002Fengineering\u002Fsystem-design\u002Fagentic-platform\u002Finterfaces\u002Fchannel-gateway","Channel gateway","The only layer that knows both an interactive channel and the platform. One message shape converges inbound, one intent shape diverges outbound, and no model call happens here.",3,[208,235,236,237,238,199],"slack","web","identity","sessions","2026-08-30",{"path":241,"title":242,"description":243,"group":139,"section":181,"order":244,"tags":245,"lastUpdated":210},"\u002Fengineering\u002Fsystem-design\u002Fagentic-platform\u002Finterfaces\u002Ffront-door","Front door","The conversational control layer. It turns a request into one structured decision, then deterministic application code answers or hands work to RunManager.",4,[246,247,197,184,198,217],"front-door","routing",{"path":249,"title":250,"description":251,"group":139,"section":181,"order":32,"tags":252,"lastUpdated":259},"\u002Fengineering\u002Fsystem-design\u002Fagentic-platform\u002Finterfaces\u002Fsurfaces","Surfaces","Every product surface and its API contract. Web chat goes through the gateway; every schema-native surface calls the domain API.",[253,254,24,255,256,257,258,217,64],"surfaces","api","approvals","prospects","saved-searches","builder","2026-09-03",{"path":261,"title":262,"description":263,"group":139,"section":181,"order":264,"tags":265,"lastUpdated":188},"\u002Fengineering\u002Fsystem-design\u002Fagentic-platform\u002Finterfaces\u002Ftriggers","Triggers","A Run with no person. Every producer emits one Event, matching is deterministic, and dispatch reuses RunManager, Policy and Inngest.",5,[266,267,142,200],"triggers","events",{"path":269,"title":270,"description":271,"group":139,"section":181,"order":272,"tags":273,"lastUpdated":259},"\u002Fengineering\u002Fsystem-design\u002Fagentic-platform\u002Fplanes\u002Fidempotency","Idempotency","One durable PostgreSQL key service prevents duplicate effects and freezes mutable input before selected Run starts. A Run start is guarded by a unique index on the Run row.",14,[200,217,194,274,275],"webhooks","reliability",{"path":277,"title":278,"description":279,"group":139,"section":181,"order":280,"tags":281,"lastUpdated":285},"\u002Fengineering\u002Fsystem-design\u002Fagentic-platform\u002Fplanes\u002Fobservability-and-operations","Observability and operations","One run row, one span tree and one usage meter. Sentry reports system failure; AgencyCore spans explain what the agent did.",13,[209,217,282,283,64,284],"spans","usage","sentry","2026-08-26",{"path":287,"title":288,"description":289,"group":139,"section":181,"order":290,"tags":291,"lastUpdated":295},"\u002Fengineering\u002Fsystem-design\u002Fagentic-platform\u002Fplanes\u002Fpolicy-and-governance","Policy and governance","One deterministic plane answers may this happen, at three checkpoints, with one grant model, one approval model and one decision log.",12,[198,292,255,293,294],"permissions","limits","governance","2026-08-25",{"path":297,"title":6,"description":298,"group":139,"section":299,"order":22,"tags":300,"lastUpdated":210},"\u002Fengineering\u002Fsystem-design\u002Fagentic-platform\u002Fproducts\u002Fagentic-crm","The AgencyCore CRM loop for turning signals and discovery into qualified organization prospects, CRM relationships and outreach.","Agentic products",[11,301,51,302,256,35,303,304,87],"lead-generation","intelligence","signals-search","email-sequence",{"path":306,"title":307,"description":308,"group":139,"section":299,"order":264,"tags":309,"lastUpdated":188},"\u002Fengineering\u002Fsystem-design\u002Fagentic-platform\u002Fproducts\u002Fbuilder-chat","Front door builder chat","Conversational authoring for organization-specific Agent and Workflow definitions, entered through the normal Front Door and backed by the existing DefinitionService.",[310,311,246,12,312,313,198],"authoring","definitions","workflows","templates",{"path":315,"title":316,"description":317,"group":139,"section":181,"order":318,"tags":319,"lastUpdated":201},"\u002Fengineering\u002Fsystem-design\u002Fagentic-platform\u002Fproducts\u002Fcapability-contracts","Company, People and Signals contracts","The five Phase 7 product capabilities, their bounded inputs, stable references, permissions and results.",21,[320,321,119,51,322],"capabilities","company","contracts",{"path":324,"title":325,"description":326,"group":139,"section":181,"order":327,"tags":328,"lastUpdated":330},"\u002Fengineering\u002Fsystem-design\u002Fagentic-platform\u002Fproducts\u002Fcapability-scenarios","Capability design scenarios","Normal, failure and recovery cases for the Phase 7 capability contracts, with implementation owners.",22,[320,329,321,119,51],"validation","2026-09-05",{"path":332,"title":333,"description":334,"group":139,"section":299,"order":233,"tags":335,"lastUpdated":210},"\u002Fengineering\u002Fsystem-design\u002Fagentic-platform\u002Fproducts\u002Femail-sequence","Email sequence workflow","Envoy durable outreach for one or many people, with fresh context, approvals, reply waits, follow-ups and Nylas transport.",[336,87,34,142,93,255],"email",{"path":338,"title":339,"description":340,"group":139,"section":299,"order":244,"tags":341,"lastUpdated":188},"\u002Fengineering\u002Fsystem-design\u002Fagentic-platform\u002Fproducts\u002Fgeneral-chat","Front door general chat","The default conversational answer path for AgencyCore. It answers from supplied context, cites what it used, asks when context is insufficient, and delegates real work through the normal Front Door.",[24,246,186,184,247,342],"citations",{"path":344,"title":345,"description":346,"group":139,"section":299,"order":222,"tags":347,"lastUpdated":188},"\u002Fengineering\u002Fsystem-design\u002Fagentic-platform\u002Fproducts\u002Fhuman-review","Human review inbox","One product page for every agentic action that is paused because a person must authorize an exact proposal. It is a view over the shared approval primitive, not a second review system.",[348,255,349,198,12],"human-review","inbox",{"path":351,"title":352,"description":353,"group":139,"section":299,"order":32,"tags":354,"lastUpdated":259},"\u002Fengineering\u002Fsystem-design\u002Fagentic-platform\u002Fproducts\u002Fsignals-search","Signals Search","One bounded discovery workflow that finds companies, verifies signals, finds relevant people, and produces evidence-backed organization prospects without prematurely creating CRM records.",[303,355,36,119,51,302,256,11,35],"discovery",{"path":357,"title":358,"description":359,"group":139,"section":299,"order":360,"tags":361,"lastUpdated":188},"\u002Fengineering\u002Fsystem-design\u002Fagentic-platform\u002Fproducts\u002Fworkflow-visualizer","Workflow visualizer","One constrained workflow graph, reused to author a draft, read a published definition, and watch a Run. Build mode edits the draft; run mode overlays Run and span state on the frozen snapshot.",7,[312,362,258,311,217,282,363,255],"visualizer","graph",{"path":365,"title":366,"description":367,"group":139,"section":181,"order":368,"tags":369,"lastUpdated":201},"\u002Fengineering\u002Fsystem-design\u002Fagentic-platform\u002Fruntime\u002Fdefinitions","Runtime definitions","Editable drafts, one published configuration per definition, template forks, deterministic validation, and the Run snapshot that keeps in flight work stable.",8,[149,311,329,370],"publishing",{"path":372,"title":373,"description":374,"group":139,"section":181,"order":375,"tags":376,"lastUpdated":259},"\u002Fengineering\u002Fsystem-design\u002Fagentic-platform\u002Fruntime\u002Fexecution","Runtime execution","The Run record, the Inngest step boundaries, agent segments, workflow nodes, approvals, cancellation, failure handling and live events.",9,[149,217,197,142,255,377,64],"cancellation",{"path":379,"title":380,"description":381,"group":139,"section":181,"order":360,"tags":382,"lastUpdated":285},"\u002Fengineering\u002Fsystem-design\u002Fagentic-platform\u002Fruntime","Agentic runtime","One Run contract, one Agno agent runtime, one deterministic workflow model, and the component boundaries that keep the framework replaceable.",[149,217,197,312,207,142],{"path":384,"title":385,"description":386,"group":139,"section":387,"order":244,"tags":388,"lastUpdated":392},"\u002Fengineering\u002Fsystem-design\u002Fmission-control\u002Fcompany-context","Company context","L3. Company state, knowledge and memory are three different things. One deterministic builder turns them into one brief.","Mission Control",[389,390,186,185,184,391,11],"mission-control","company-state","retrieval","2026-08-12",{"path":394,"title":395,"description":396,"group":139,"section":387,"order":22,"tags":397,"lastUpdated":392},"\u002Fengineering\u002Fsystem-design\u002Fmission-control\u002Fexperience","Experience","L6. Where a person observes and controls the company, and the one rule that keeps the UI out of the business.",[389,398,399,255,400],"ui","control-plane","activity",{"path":402,"title":403,"description":404,"group":139,"section":387,"order":222,"tags":405,"lastUpdated":392},"\u002Fengineering\u002Fsystem-design\u002Fmission-control\u002Ffoundation","Foundation","L1. Generic infrastructure with no business logic in it. The test is that another product could run on it unchanged.",[389,406,407,408,267,409,226,209],"infrastructure","database","queue","storage",{"path":411,"title":387,"description":412,"group":139,"section":214,"order":233,"tags":413,"lastUpdated":392},"\u002Fengineering\u002Fsystem-design\u002Fmission-control","The internal Company OS. Six layers and one policy plane put a person in control of company state and of autonomous execution.",[389,414,14,12,312,198,399],"company-os",{"path":416,"title":417,"description":418,"group":139,"section":387,"order":32,"tags":419,"lastUpdated":392},"\u002Fengineering\u002Fsystem-design\u002Fmission-control\u002Fintelligence","Intelligence","L5. The agent is the primitive. A skill is how it works, a tool is how it reaches the world, and the two are never the same thing.",[389,12,207,420,421],"planning","reasoning",{"path":423,"title":424,"description":425,"group":139,"section":387,"order":368,"tags":426,"lastUpdated":392},"\u002Fengineering\u002Fsystem-design\u002Fmission-control\u002Fmetrics-and-connectors","Metrics and connectors","A worked example across every layer. Three vendors, one metric pipeline, three views, and the rule that decides what we store.",[389,427,195,428,429,284,430,431],"metrics","stripe","posthog","ingest","dashboards",{"path":433,"title":434,"description":435,"group":139,"section":387,"order":233,"tags":436,"lastUpdated":392},"\u002Fengineering\u002Fsystem-design\u002Fmission-control\u002Forchestration","Orchestration","L4. Workflow, run, step, trigger and event. Five nouns that turn a decision into durable execution.",[389,312,217,266,267,437,438],"durability","retry",{"path":440,"title":288,"description":441,"group":139,"section":387,"order":360,"tags":442,"lastUpdated":392},"\u002Fengineering\u002Fsystem-design\u002Fmission-control\u002Fpolicy-and-governance","A plane, not a layer. One place decides what an agent may do, under what conditions, and how much. Human approval is one of its three answers.",[389,198,294,255,292,293,443],"audit",{"path":445,"title":191,"description":446,"group":139,"section":387,"order":264,"tags":447,"lastUpdated":392},"\u002Fengineering\u002Fsystem-design\u002Fmission-control\u002Ftools-and-integrations","L2. One contract for every capability. The tool is the only route to the world, and it is where policy, audit and tenancy meet.",[389,194,195,448,449,450],"adapters","registry","credentials",{"path":452,"title":453,"description":454,"group":139,"section":455,"order":22,"tags":456,"lastUpdated":210},"\u002Fengineering\u002Fsystem-design\u002Fworkflows\u002Fcompany-search","Company search","Implementation notes for company.search. Search resolves and gates company identities; enrichment is a separate capability.","Workflows",[321,457,142,42],"search",{"path":459,"title":31,"description":460,"group":139,"section":455,"order":233,"tags":461,"lastUpdated":210},"\u002Fengineering\u002Fsystem-design\u002Fworkflows\u002Fenrichment","Reusable company and people enrichment workflows with canonical Intelligence write-back, existing tier freshness and bounded asynchronous email.",[35,321,119,142],{"path":463,"title":464,"description":465,"group":139,"section":455,"order":32,"tags":466,"lastUpdated":259},"\u002Fengineering\u002Fsystem-design\u002Fworkflows\u002Fpeople-search","People search","Implementation notes for people.search. Bounded company scope and persona gates return selectable person identities without enrichment.",[119,457,142,100],{"path":468,"title":469,"description":470,"group":139,"section":455,"order":244,"tags":471,"lastUpdated":474},"\u002Fengineering\u002Fsystem-design\u002Fworkflows\u002Fsignals-search","Signals search","Superseded. The earlier on-demand buying-signal search component, kept as a record of the design that the agentic platform Signals Search workflow replaces.",[51,12,142,472,473],"intelligence-databases","superseded","2026-08-28",{"path":476,"title":477,"description":478,"group":479,"section":480,"order":481,"tags":482,"lastUpdated":66},"\u002Flearnings\u002Fagentic-sdlc","The agentic SDLC","How AI agents move from autocomplete to owning the loop across the software lifecycle, and why that shifts the bottleneck from coding to verification.","Learnings",null,30,[12,483,484,485,486],"sdlc","engineering","verification","review",{"path":488,"title":489,"description":490,"group":479,"section":480,"order":491,"tags":492,"lastUpdated":498},"\u002Flearnings\u002Fagi-to-asi","From AGI to ASI","What lies beyond human-level AI. The four technological pathways from AGI to artificial superintelligence, the formal ceiling that bounds them, and the six bottlenecks that could stall the climb - distilled from the DeepMind report.",50,[493,494,495,496,497],"ai-futures","asi","agi","scaling","recursive-self-improvement","2026-06-19",{"path":500,"title":501,"description":502,"group":479,"section":480,"order":503,"tags":504,"lastUpdated":66},"\u002Flearnings\u002Fai-native-company-playbook","AI native company playbook","Why AI should be the operating system your company runs on, not a tool it uses, and the concrete practices that follow - closed loops, a queryable org, software factories, and token maxing.",40,[505,506,12,507,508],"ai-native","company-building","gtm","founders",{"path":510,"title":511,"description":512,"group":479,"section":480,"order":157,"tags":513,"lastUpdated":54},"\u002Flearnings\u002Fbuying-intent-signals","Buying intent signals","How buyers leak their intent before they ever fill in a form, and how to read those signals before the window closes.",[514,51,507,515],"intent","sales",{"path":517,"title":518,"description":519,"group":479,"section":480,"order":520,"tags":521,"lastUpdated":54},"\u002Flearnings\u002Fcold-outbound-system","Cold outbound system","A high-level study of an open-source 29-skill cold email system, organized into five sequential tracks from ICP to iteration.",20,[522,523,507,524],"outbound","cold-email","systems",{"path":526,"title":527,"description":528,"group":479,"section":480,"order":529,"tags":530,"lastUpdated":532},"\u002Flearnings\u002Fswan-gtm-skills-architecture","Swan GTM skills architecture","A research note on Swan AI's foundations and maps model for GTM agents, with ASCII diagrams and ideas AgencyCore can borrow.",60,[507,12,73,531,14],"swan","2026-07-01",{"path":534,"title":535,"description":536,"group":387,"section":480,"order":272,"tags":537,"lastUpdated":43},"\u002Fmission-control\u002Fciops-agent","CIOps agent","High-level system architecture and design notes for the Mission Control CIOps agent.",[389,12,538,14],"ciops",{"path":540,"title":541,"description":542,"group":387,"section":480,"order":182,"tags":543,"lastUpdated":43},"\u002Fmission-control\u002Fcostops-agent","CostOps agent","High-level system architecture and design notes for the Mission Control CostOps agent.",[389,12,544,14],"finops",{"path":546,"title":547,"description":548,"group":387,"section":480,"order":520,"tags":549,"lastUpdated":54},"\u002Fmission-control\u002Fdashboard","Dashboard","The Mission Control product UI - a dark cockpit with a fleet-nav rail, company-state grid, a working escalation queue, live ledger and a global kill switch.",[389,12,550,398],"dashboard",{"path":552,"title":553,"description":554,"group":387,"section":480,"order":280,"tags":555,"lastUpdated":43},"\u002Fmission-control\u002Fproduct-analytics-agent","ProductAnalytics agent","High-level system architecture and design notes for the Mission Control ProductAnalytics agent.",[389,12,556,14],"product-analytics",{"path":558,"title":559,"description":560,"group":387,"section":480,"order":290,"tags":561,"lastUpdated":43},"\u002Fmission-control\u002Frevenueops-agent","RevenueOps agent","High-level system architecture and design notes for the Mission Control RevenueOps agent.",[389,12,562,14],"revops",{"path":564,"title":214,"description":565,"group":387,"section":480,"order":157,"tags":566,"lastUpdated":54},"\u002Fmission-control\u002Fsystem-design","One screen for the whole company, watched by a guardrailed fleet of ops agents that explain, propose, act and learn overnight.",[389,12,544,14],{"path":568,"title":569,"description":570,"group":571,"section":480,"order":32,"tags":572,"lastUpdated":578},"\u002Fproduct-design\u002Fonboarding-flow","Onboarding flow","Product design for the signup wizard and how TAM building folds into it. Analyzes the flow today (account, profile, company), the gap (no ICP, empty dashboard), and the integration of a new \"who you sell to\" ICP step plus a build-and-reveal screen that lands the user on a populated, ranked list.","Product Design",[573,61,574,575,576,577],"onboarding","tam","activation","ux","user-journey","2026-06-11",{"path":580,"title":581,"description":582,"group":571,"section":480,"order":233,"tags":583,"lastUpdated":592},"\u002Fproduct-design\u002Fpricing-entitlements","Pricing tiers, entitlements and usage credits","Specification for subscription tiers with gated platform access: composable plan entitlements, a unified usage-credit currency, plan-sourced limits, per-module trials and a two-ticket delivery plan built on the Stripe billing foundation. Written for discussion; the Linear document is the canonical copy with ticket links.",[584,585,586,587,588,589,590,591],"pricing","entitlements","billing","credits","subscriptions","plans","seats","trials","2026-07-06",{"path":594,"title":595,"description":596,"group":571,"section":480,"order":233,"tags":597,"lastUpdated":578},"\u002Fproduct-design\u002Fsales-signals-ux","Designing Signals","Product design for the sales-signals experience in ac-frontend: the 14-type taxonomy and its color system, the anatomy of a signal card across four densities, the 0-10 lead score scale, the origin tag (sonar pull vs proactive push), the seven surfaces where signals render (launchpad, sonar app, company detail, timeline, activities, data layer, Envoy), and the interaction rules that keep them consistent.",[51,576,598,11,42,599,600,601,602],"design-system","lead-score","origin","pull","push",{"path":604,"title":605,"description":606,"group":607,"section":608,"order":244,"tags":609,"lastUpdated":43},"\u002Fproprietary-data\u002Fcrm\u002Factivities","Activities","Deep dive on crm_activities, the interaction + task log of the CRM — where it is served from, how a row is born and read, and its full schema, relationships and rules.","Proprietary data","CRM",[11,610,611,612,613],"activities","tasks","data-model","schema",{"path":615,"title":616,"description":617,"group":607,"section":608,"order":264,"tags":618,"lastUpdated":43},"\u002Fproprietary-data\u002Fcrm\u002Fcommunications","Communications","Deep dive on crm_communications and crm_communication_events, the unified email\u002Fcall\u002Fmessage log and its per-message engagement tracking — where it is served from, the outbound message lifecycle, and the full schema, relationships and rules.",[11,619,336,620,612],"communications","engagement",{"path":622,"title":623,"description":624,"group":607,"section":608,"order":22,"tags":625,"lastUpdated":43},"\u002Fproprietary-data\u002Fcrm\u002Fcompanies","Companies","Deep dive on crm_companies, the account record at the centre of the CRM — where it is served from, how a row is born and read, and its full schema, relationships and rules.",[11,36,612,613,14],{"path":627,"title":628,"description":629,"group":607,"section":608,"order":233,"tags":630,"lastUpdated":43},"\u002Fproprietary-data\u002Fcrm\u002Fdeals","Deals","Deep dive on the deal pipeline — crm_deals, crm_pipeline_stages and crm_pipeline_config. Where it is served from, the life of a deal, and its full schema, relationships and rules.",[11,631,632,612,613],"deals","pipeline",{"path":634,"title":635,"description":636,"group":607,"section":608,"order":222,"tags":637,"lastUpdated":43},"\u002Fproprietary-data\u002Fcrm\u002Flists","Lists","Deep dive on crm_lists and crm_list_members, the static or dynamic member collections of the CRM — where they are served from, how a list and its members come to be and are read, and their schema, relationships and rules.",[11,638,639,612,613],"lists","segments",{"path":641,"title":642,"description":643,"group":607,"section":608,"order":32,"tags":644,"lastUpdated":43},"\u002Fproprietary-data\u002Fcrm\u002Fpeople","People","Deep dive on crm_people, the contact record of the CRM — where it is served from, how a row is born and read, and its full schema, relationships and rules.",[11,119,645,612,613],"contacts",{"path":647,"title":648,"description":649,"group":607,"section":608,"order":368,"tags":650,"lastUpdated":43},"\u002Fproprietary-data\u002Fcrm\u002Fsaved-filters","Saved filters","Deep dive on crm_saved_filters, the named reusable filter snapshots over the company, person and signal list views — where it is served from, how a saved view is born and applied, and its full schema, relationships and rules.",[11,651,652,612,613],"saved-filters","views",{"path":654,"title":655,"description":656,"group":607,"section":608,"order":360,"tags":657,"lastUpdated":578},"\u002Fproprietary-data\u002Fcrm\u002Fsignals","Signals","Deep dive on the signals tables - signals, company_signals and person_signals, the CRM's sales-intelligence layer. Where signals are served from, how one is born and attached, and the full schema, relationships and rules.",[11,51,302,612,613],{"path":659,"title":660,"description":661,"group":607,"section":662,"order":22,"tags":663,"lastUpdated":43},"\u002Fproprietary-data\u002Fintelligence-databases\u002Fcompany-intelligence-database","Company Intelligence Database","Decided architecture for ENG-669, the cross-org company intelligence layer that acts as a read-through cache in front of enrichment providers, with public-facts-only privacy and provenance-tracked write-back.","Intelligence databases",[14,60,36,51,38,664],"eng-669",{"path":666,"title":667,"description":668,"group":607,"section":662,"order":244,"tags":669,"lastUpdated":578},"\u002Fproprietary-data\u002Fintelligence-databases\u002Forg-signal-feed","Org Signal Feed","The per-org activation layer on top of the shared signals store. One immutable intel_signals row fans out to many orgs through scoring (signal-type weight times ICP fit times recency decay) and materializes as ranked, tiered rows in intel_org_signal_feed - the only org-scoped, RLS-per-org table of the signal stack, the door the launchpad, inbox and digest all read through. Signals enter by two ingest classes - a user's sonar pull (ungated) or an automated push (gated by threshold plus an optional competitor-ICP check) - logged in intel_signal_ingests, and each feed row records its origin.",[14,60,51,670,53,671,672,575,430,601,602,600],"feed","decay","rls",{"path":674,"title":675,"description":676,"group":607,"section":662,"order":32,"tags":677,"lastUpdated":578},"\u002Fproprietary-data\u002Fintelligence-databases\u002Fpeople-intelligence-database","People Intelligence Database","Decided architecture for the cross-org people intelligence layer - a read-through cache in front of headhunter research and Hunter email lookups, with LinkedIn-URL identity, append-only employment edges, per-tier freshness stamps on the flat profile, shared intel_sources provenance, unified intel_signals, and a GDPR erasure path.",[14,60,119,51,38,100],{"path":679,"title":680,"description":681,"group":607,"section":662,"order":233,"tags":682,"lastUpdated":578},"\u002Fproprietary-data\u002Fintelligence-databases\u002Fsignals-intelligence-database","Signals Intelligence Database","Decided v1 architecture for the unified signal store - one polymorphic append-only intel_signals table that holds both company and person signals, with a shared taxonomy, source-ranked provenance, an intel_signal_ingests log that records which pipeline found each signal, decay at read time, and a person-to-company rollup so a champion job change surfaces on the company feed.",[14,60,51,683,671,684,670,685,41,601,602],"polymorphic","taxonomy","ingests",{"path":687,"title":688,"description":689,"group":607,"section":480,"order":9,"tags":690,"lastUpdated":16},"\u002Fproprietary-data\u002Foverview","Data Layer Overview","The AgencyCore data layer in one map - the org-scoped CRM plane in production today and the global intelligence plane designed to sit in front of it, with interactive diagrams of both, the end-to-end data flow, freshness and precedence rules, the privacy seam, and the rollout path.",[691,14,60,11,51,38,25,216],"data-layer",{"path":693,"title":694,"description":695,"group":696,"section":480,"order":9,"tags":697,"lastUpdated":54},"\u002Froadmap","Roadmap - June 2026","June 2026 product plan across four themes. The spine is moving our agents onto an isolated sandbox runtime and rebuilding the core agents and workflows on it, then standing up a read-through intelligence data store and shipping the Stripe billing system. Knowledge base, assistant, and credit tracking carry into the July roadmap.","Roadmap",[698,420],"roadmap",{"path":700,"title":701,"description":702,"group":696,"section":480,"order":22,"tags":703,"lastUpdated":54},"\u002Froadmap\u002Fjuly-2026","Roadmap - July 2026","July 2026 product plan across three themes, all carried over from June. Building on June's sandbox runtime, July grounds the agents in a knowledge base, launches the AI chat assistant, and meters every action with per-action credit tracking that reconciles into the Stripe billing system shipped in June.",[698,420],{"path":705,"title":706,"description":707,"group":696,"section":480,"order":32,"tags":708,"lastUpdated":532},"\u002Froadmap\u002Fjune-2026-slides","Roadmap slides - June 2026","Board-review slide deck for the June 2026 product roadmap, rendered directly from the original PPTX in the docs site.",[698,420,709],"slides",{"path":711,"title":712,"description":713,"group":714,"section":8,"order":520,"tags":715,"lastUpdated":16},"\u002Fsymphony\u002Fagents\u002Fdevops-agent","DevOps agent","Interactive design for a Slack-first Symphony DevOps agent that wraps production promotion, rollback, audit, and operational jobs behind policy gates, typed runbooks, and an auditable ledger.","Symphony",[716,235,717,718,719,720],"symphony","devops","production","runbooks","operations",{"path":722,"title":723,"description":724,"group":714,"section":8,"order":157,"tags":725,"lastUpdated":16},"\u002Fsymphony\u002Fagents\u002Foncall-agent","Oncall agent","Interactive design for a Symphony oncall agent that turns Sentry incidents into rich Linear tickets, investigates with Codex, opens fix PRs, and resolves Sentry after merge.",[716,284,726,727,728,729],"linear","oncall","incident-response","codex",{"path":731,"title":732,"description":733,"group":714,"section":734,"order":157,"tags":735,"lastUpdated":16},"\u002Fsymphony\u002Fhousekeeping\u002Fcodex-vacuum","Codex vacuum","Interactive design for the Symphony housekeeping timer that checkpoints and vacuums Codex sqlite stores on the VPS.","Housekeeping",[716,736,737,729,738,739],"timed-jobs","housekeeping","sqlite","vps",{"path":741,"title":742,"description":743,"group":714,"section":734,"order":481,"tags":744,"lastUpdated":16},"\u002Fsymphony\u002Fhousekeeping\u002Fhost-cleanup","Host cleanup","Interactive design for the Symphony housekeeping timer that removes stale \u002Ftmp debris, vacuums the journal, and optionally cleans the apt package cache.",[716,736,737,739,745,746],"disk","cleanup",{"path":748,"title":749,"description":750,"group":714,"section":734,"order":520,"tags":751,"lastUpdated":16},"\u002Fsymphony\u002Fhousekeeping\u002Fworkspace-cleanup","Workspace cleanup","Interactive design for the Symphony housekeeping timer that prunes idle per-issue workspaces after their TTL.",[716,736,737,752,746,739],"workspaces",{"path":754,"title":755,"description":756,"group":714,"section":480,"order":9,"tags":757,"lastUpdated":66},"\u002Fsymphony","Symphony orchestration","How AgencyCore runs OpenAI Symphony as a long-running daemon that turns Linear tickets into isolated, autonomous Codex runs, reviewed by Claude and merged by humans. High-level workflow, system architecture, and the engineer playbook.",[716,729,726,758,111,739,759,760],"claude-review","qa","automation",{"path":762,"title":763,"description":764,"group":714,"section":214,"order":22,"tags":765,"lastUpdated":392},"\u002Fsymphony\u002Fsystem-design\u002Fhigh-level-design","High-level design","The Symphony daemon end to end — the standing agent workforce and its label-routed workflows, then the runtime that polls, dispatches, runs and writes back.",[716,14,111,12,729,726,766],"systemd",{"path":768,"title":769,"description":770,"group":714,"section":771,"order":503,"tags":772,"lastUpdated":16},"\u002Fsymphony\u002Ftimed-jobs\u002Fdaily-security-agent","Daily security agent","Interactive design for a report-only Symphony timed job that reviews the last 24h of commits, scans the system for vulnerabilities, and opens focused follow-up tickets.","Timed jobs",[716,199,736,729,773,774,775],"semgrep","threat-model","ownership",{"path":777,"title":778,"description":779,"group":714,"section":771,"order":481,"tags":780,"lastUpdated":16},"\u002Fsymphony\u002Ftimed-jobs\u002Fdaily-sentry-triage","Daily Sentry triage","Interactive design for the Symphony timed job that performs read-only Sentry triage, deduplicates existing tracked clusters, and creates focused ENG bugs for new actionable errors.",[716,736,284,209,781,726],"triage",{"path":783,"title":784,"description":785,"group":714,"section":771,"order":157,"tags":786,"lastUpdated":16},"\u002Fsymphony\u002Ftimed-jobs\u002Fnightly-local-staging-e2e","Nightly local staging E2E","Interactive design for the Symphony timed job that seeds local Supabase, runs ac-frontend Playwright E2E against the local staging stack, uploads evidence, and cleans artifacts.",[716,736,787,788,789,790],"e2e","playwright","staging","frontend",{"path":792,"title":793,"description":794,"group":714,"section":771,"order":520,"tags":795,"lastUpdated":16},"\u002Fsymphony\u002Ftimed-jobs\u002Fnightly-staging-qa","Nightly staging QA","Interactive design for the Symphony timed job that seeds a staging QA Linear issue, runs an agent-browser crawl, validates feature-map coverage, and files focused follow-up work.",[716,736,789,759,796,726],"agent-browser",{"id":798,"title":204,"body":799,"customComponent":480,"description":205,"extension":3708,"group":139,"lastUpdated":210,"meta":3709,"navigation":1621,"order":22,"path":203,"related":3710,"section":181,"seo":3731,"stem":3732,"tags":3733,"__hash__":3734},"docs\u002Fengineering\u002Fsystem-design\u002Fagentic-platform\u002Fcontract.md",{"type":800,"value":801,"toc":3683},"minimark",[802,806,818,826,838,848,851,858,863,1006,1013,1017,1045,1052,1055,1059,1153,1157,1242,1246,1252,1255,1259,1484,1488,1494,1501,1504,1538,1558,1561,1597,1601,1607,1633,1654,1711,1720,1730,1759,1764,1770,1780,1798,1820,1826,1832,1864,1883,1909,1933,1938,1981,2005,2022,2032,2035,2043,2063,2078,2084,2136,2160,2164,2167,2257,2260,2298,2302,2305,2311,2314,2318,2321,2327,2334,2340,2343,2361,2375,2387,2391,2402,2405,2714,2734,2737,2741,2744,2789,2795,2802,2821,2825,2832,2843,2877,2893,2904,2924,2928,2939,2970,2976,2978,2998,3202,3205,3222,3226,3316,3320,3323,3580,3584,3587,3656,3659,3673,3679],[803,804,204],"h1",{"id":805},"platform-contract",[807,808,809],"blockquote",{},[810,811,812,813,817],"p",{},"This page is the contract behind the ",[814,815,816],"a",{"href":212},"agentic platform overview",". Read the overview first for the one-page diagram and the whole path from a request to a result.",[810,819,820,821,825],{},"The platform has ",[822,823,824],"strong",{},"one run boundary",". Two paths reach it today, and the invariant worth defending is the boundary, not the count.",[810,827,828,829,833,834,837],{},"An outside AI agent is a third caller. It works today only by driving the ",[830,831,832],"code",{},"ac"," CLI on a user's seat, so it enters through the normal product API. An MCP server is not built and not designed. See ",[814,835,836],{"href":219},"agent access",".",[839,840,846],"pre",{"className":841,"code":843,"language":844,"meta":845},[842],"language-text","Person \u002F interactive channel                 Event \u002F schedule \u002F webhook\n            │                                            │\n            ▼                                            ▼\n     Channel Gateway                                  Triggers\n            │                                            │\n            ▼                                            │\n       Front Door                                        │\n            └──────────────┬─────────────────────────────┘\n                           ▼\n                   StartRunCommand\n                           │\n                           ▼\n                       RunManager\n                           │\n                    Policy admission\n                           │\n                           ▼\n                         Inngest\n                           │\n                  ┌────────┴────────┐\n                  ▼                 ▼\n            Agent execution   Workflow execution\n                  │                 │\n                  └────────┬────────┘\n                           ▼\n                         Tools\n                           │\n                           ▼\n                 services \u002F vendors \u002F MCP\n\n          Context \u002F State             Policy\n                ▲                  admission\u002Faction\u002Faccrual\n                │\n             Runtime                 Observability\n                                      spans + usage\n","text","",[830,847,843],{"__ignoreMap":845},[810,849,850],{},"The newest V1 decision is deliberately simple:",[807,852,853],{},[810,854,855],{},[822,856,857],{},"Agno is the only agent runtime. Inngest owns durable coordination. AgencyCore owns product state, definitions, tools, policy, context, approvals and observability.",[859,860,862],"h2",{"id":861},"what-we-build","What we build",[864,865,866,879],"table",{},[867,868,869],"thead",{},[870,871,872,876],"tr",{},[873,874,875],"th",{},"Need",[873,877,878],{},"Owner",[880,881,882,891,899,907,914,924,932,940,951,959,967,979,987,994],"tbody",{},[870,883,884,888],{},[885,886,887],"td",{},"Conversational routing to role-specific Agents\u002FWorkflows",[885,889,890],{},"Front Door",[870,892,893,896],{},[885,894,895],{},"Interactive chat transport: web chat in the current V1 slice. Slack, Telegram and WhatsApp later",[885,897,898],{},"Channel Gateway",[870,900,901,904],{},[885,902,903],{},"Email receive\u002Fsend",[885,905,906],{},"Nylas producer + email tools, not Channel Gateway",[870,908,909,912],{},[885,910,911],{},"Event\u002Fschedule initiated work",[885,913,262],{},[870,915,916,919],{},[885,917,918],{},"Routing one event to a new Run and to a waiting Run",[885,920,921],{},[830,922,923],{},"EventRouter",[870,925,926,929],{},[885,927,928],{},"Authoring triggers, policies and connections",[885,930,931],{},"The three admin surfaces",[870,933,934,937],{},[885,935,936],{},"Long-running\u002Fretryable execution",[885,938,939],{},"RunManager + Inngest",[870,941,942,945],{},[885,943,944],{},"Agent model loop",[885,946,947,948],{},"Agno through ",[830,949,950],{},"AgentRuntime",[870,952,953,956],{},[885,954,955],{},"Deterministic workflows",[885,957,958],{},"Workflow executor over Inngest primitives",[870,960,961,964],{},[885,962,963],{},"Internal\u002Fvendor actions now. MCP actions later",[885,965,966],{},"Tools & Integrations",[870,968,969,972],{},[885,970,971],{},"Human approval",[885,973,974,975,978],{},"Policy decision + ",[830,976,977],{},"agent.approvals"," + Inngest wait",[870,980,981,984],{},[885,982,983],{},"Context, memory, knowledge, CRM reads",[885,985,986],{},"State & Knowledge",[870,988,989,992],{},[885,990,991],{},"Duplicate command protection",[885,993,270],{},[870,995,996,999],{},[885,997,998],{},"Auditable execution record",[885,1000,1001,1002,1005],{},"Runs + ",[830,1003,1004],{},"agent.spans"," + usage meter",[810,1007,1008,1009,1012],{},"Each new feature should normally become ",[822,1010,1011],{},"data + a surface\u002Fadapter",", not a new infrastructure subsystem.",[859,1014,1016],{"id":1015},"product-capability-contracts","Product capability contracts",[810,1018,1019,1020,1023,1024,1023,1027,1023,1030,1033,1034,1037,1038,1040,1041,1044],{},"Phase 7 exposes five stable product IDs: ",[830,1021,1022],{},"company.search",", ",[830,1025,1026],{},"company.enrich",[830,1028,1029],{},"people.search",[830,1031,1032],{},"people.enrich"," and ",[830,1035,1036],{},"signals.search",".\nThe ",[814,1039,316],{"href":315}," own their schemas, permissions, references, source coverage and enrichment presets.\nThe ",[814,1042,1043],{"href":324},"design scenarios"," define the expected normal and failure behavior.",[810,1046,1047,1048,1051],{},"A capability names a business action. A published tenant Workflow executes it.\nThe registry resolves a stable ID to that Workflow's UUID. Every caller still enters through ",[830,1049,1050],{},"RunManager",".\nA Tool remains a technical operation. A capability adds neither a runtime nor a workflow node type.",[810,1053,1054],{},"Search and Enrich are separate operations. Search returns stable references; Enrich writes canonical Intelligence.\nThe product surface carries selected refs between them. CRM and list writes remain explicit actions.\nThe Front Door delegates once per turn. Published workflows may compose child workflows under the existing grant, snapshot and cost rules.",[859,1056,1058],{"id":1057},"core-principles","Core principles",[1060,1061,1062,1069,1075,1081,1087,1093,1099,1105,1111,1117,1123,1129,1135,1141,1147],"ol",{},[1063,1064,1065,1068],"li",{},[822,1066,1067],{},"One product execution substrate."," One Run model, one status model, one event surface.",[1063,1070,1071,1074],{},[822,1072,1073],{},"One agent framework in V1."," Agno runs reasoning loops; there is no backend router or managed-agent backend in the target architecture.",[1063,1076,1077,1080],{},[822,1078,1079],{},"Definitions are data."," Agent, Workflow and Skill definitions live in the database.",[1063,1082,1083,1086],{},[822,1084,1085],{},"Publishing is a safety boundary, not a revision system."," Draft → validate → current published configuration. Runs freeze snapshots.",[1063,1088,1089,1092],{},[822,1090,1091],{},"One agentic hop."," The Front Door selects one Agent or Workflow. Deterministic workflow coordination is not another reasoning hop.",[1063,1094,1095,1098],{},[822,1096,1097],{},"An Agent reaches the world only through a Tool."," No credentials, direct repositories, raw SQL or arbitrary API access in model context.",[1063,1100,1101,1104],{},[822,1102,1103],{},"A Skill teaches; a Tool acts; a Workflow coordinates."," Do not collapse the three.",[1063,1106,1107,1110],{},[822,1108,1109],{},"The channel is a rendering detail."," Agents do not learn Slack\u002FTelegram\u002FWhatsApp-specific behavior.",[1063,1112,1113,1116],{},[822,1114,1115],{},"Email is not an interactive channel primitive."," Nylas owns email transport; email enters through events and tools.",[1063,1118,1119,1122],{},[822,1120,1121],{},"Each fact has one owner."," Authoritative application\u002FCRM data > published knowledge > memory.",[1063,1124,1125,1128],{},[822,1126,1127],{},"Policy is one plane."," Check permission\u002Fconditions at admission, action and accrual.",[1063,1130,1131,1134],{},[822,1132,1133],{},"Policy changes are live, and so is the grant."," An in-flight Run reads the current rule set at its next checkpoint, and re-intersects its principal against the actor's current rights. Authority can shrink mid Run; it never grows.",[1063,1136,1137,1140],{},[822,1138,1139],{},"Observability is one plane."," Runs\u002Fspans\u002Fusage are the durable record; SSE is transient delivery.",[1063,1142,1143,1146],{},[822,1144,1145],{},"Idempotency protects effects, not orchestration."," Inngest retries safely only when business commands and external effects are idempotent.",[1063,1148,1149,1152],{},[822,1150,1151],{},"Keep V1 boring."," No general plugin framework, custom policy language, custom scheduler, custom durable checkpointer, or deep agent hierarchy.",[859,1154,1156],{"id":1155},"human-request-flow","Human request flow",[1060,1158,1159,1162,1172,1178,1194,1206,1211,1223,1226,1229,1236,1239],{},[1063,1160,1161],{},"Channel Gateway verifies and normalizes an interactive message.",[1063,1163,1164,1165,1167,1168,1171],{},"A verified identity becomes an actor identity; ",[830,1166,1050],{}," mints the ",[830,1169,1170],{},"Principal",". An unknown identity starts no Run.",[1063,1173,1174,1175,837],{},"Front Door builds lightweight context and queries the ",[830,1176,1177],{},"CapabilityIndex",[1063,1179,1180,1181,1023,1184,1023,1187,1190,1191,837],{},"One Agno call returns ",[830,1182,1183],{},"answer",[830,1185,1186],{},"clarify",[830,1188,1189],{},"delegate",", or ",[830,1192,1193],{},"control_run",[1063,1195,1196,1198,1199,1202,1203,837],{},[830,1197,1189],{}," becomes a shared ",[830,1200,1201],{},"StartRunCommand"," and calls ",[830,1204,1205],{},"RunManager.start()",[1063,1207,1208,1210],{},[830,1209,1050],{}," freezes the published definition, skills, tool contract, context policy and principal grant into the Run snapshot.",[1063,1212,1213,1214,1023,1217,1190,1220,837],{},"Policy admission returns ",[830,1215,1216],{},"allow",[830,1218,1219],{},"deny",[830,1221,1222],{},"require_approval",[1063,1224,1225],{},"Allowed Runs dispatch through Inngest; approval Runs wait on the same Run row.",[1063,1227,1228],{},"Runtime rebuilds fresh authorized context and executes an Agent or Workflow.",[1063,1230,1231,1232,1235],{},"Every Agent tool call returns through ",[830,1233,1234],{},"ToolInvoker"," and action policy.",[1063,1237,1238],{},"Spans and usage are written durably; live events are published for active surfaces.",[1063,1240,1241],{},"Gateway renders semantic output for the originating interactive channel.",[859,1243,1245],{"id":1244},"machine-request-flow","Machine request flow",[839,1247,1250],{"className":1248,"code":1249,"language":844,"meta":845},[842],"producer -> PlatformEvent -> EventRouter -> TriggerMatcher -> TriggerDispatchService\n         -> StartRunCommand -> RunManager -> Policy -> Inngest -> Runtime\n",[830,1251,1249],{"__ignoreMap":845},[810,1253,1254],{},"Triggers never bypass the normal Run boundary. Their service principal constrains context and tools just as a user principal does for an interactive Run.",[859,1256,1258],{"id":1257},"layer-ownership","Layer ownership",[864,1260,1261,1277],{},[867,1262,1263],{},[870,1264,1265,1268,1271,1274],{},[873,1266,1267],{},"Tier",[873,1269,1270],{},"Page",[873,1272,1273],{},"Owns",[873,1275,1276],{},"Must not own",[880,1278,1279,1295,1310,1324,1338,1352,1369,1384,1398,1412,1427,1441,1456,1470],{},[870,1280,1281,1284,1289,1292],{},[885,1282,1283],{},"Map",[885,1285,1286],{},[814,1287,1288],{"href":212},"Overview",[885,1290,1291],{},"The one-page map of the whole platform",[885,1293,1294],{},"Any detail a layer page owns",[870,1296,1297,1300,1304,1307],{},[885,1298,1299],{},"Interfaces",[885,1301,1302],{},[814,1303,250],{"href":249},[885,1305,1306],{},"Direct product APIs\u002FUI contracts",[885,1308,1309],{},"Runtime logic",[870,1311,1312,1314,1318,1321],{},[885,1313,1299],{},[885,1315,1316],{},[814,1317,231],{"href":230},[885,1319,1320],{},"Interactive transport, identity\u002Fsession mapping, rendering",[885,1322,1323],{},"Email transport, prompts, business logic",[870,1325,1326,1328,1332,1335],{},[885,1327,1299],{},[885,1329,1330],{},[814,1331,242],{"href":241},[885,1333,1334],{},"Conversation intelligence and capability selection",[885,1336,1337],{},"Task execution, approval rules, tool management",[870,1339,1340,1342,1346,1349],{},[885,1341,1299],{},[885,1343,1344],{},[814,1345,262],{"href":261},[885,1347,1348],{},"Event normalization\u002Fmatching and trigger dispatch",[885,1350,1351],{},"Policy, workflow execution, scheduler implementation",[870,1353,1354,1356,1360,1366],{},[885,1355,1299],{},[885,1357,1358],{},[814,1359,220],{"href":219},[885,1361,1362,1363],{},"How an outside AI agent reaches the platform. ",[822,1364,1365],{},"Stub, not a design",[885,1367,1368],{},"Everything below the CLI it drives",[870,1370,1371,1374,1378,1381],{},[885,1372,1373],{},"Runtime",[885,1375,1376],{},[814,1377,380],{"href":379},[885,1379,1380],{},"Runtime architecture and execution boundaries",[885,1382,1383],{},"Tool implementation, domain state",[870,1385,1386,1388,1392,1395],{},[885,1387,1373],{},[885,1389,1390],{},[814,1391,366],{"href":365},[885,1393,1394],{},"Draft\u002Fpublish\u002Fvalidate\u002Fsnapshot",[885,1396,1397],{},"Execution state",[870,1399,1400,1402,1406,1409],{},[885,1401,1373],{},[885,1403,1404],{},[814,1405,373],{"href":372},[885,1407,1408],{},"Run lifecycle, execution, waits, cancellation, live events",[885,1410,1411],{},"Definition authoring",[870,1413,1414,1417,1421,1424],{},[885,1415,1416],{},"Services",[885,1418,1419],{},[814,1420,191],{"href":190},[885,1422,1423],{},"Model-facing action boundary and integrations",[885,1425,1426],{},"Agent reasoning",[870,1428,1429,1431,1435,1438],{},[885,1430,1416],{},[885,1432,1433],{},[814,1434,179],{"href":178},[885,1436,1437],{},"Authorized context and memory\u002Fknowledge ownership",[885,1439,1440],{},"Agent-selected actions",[870,1442,1443,1446,1450,1453],{},[885,1444,1445],{},"Planes",[885,1447,1448],{},[814,1449,288],{"href":287},[885,1451,1452],{},"Permission, conditions, approval decisions, limits",[885,1454,1455],{},"Tenancy boundary, model reasoning",[870,1457,1458,1460,1464,1467],{},[885,1459,1445],{},[885,1461,1462],{},[814,1463,278],{"href":277},[885,1465,1466],{},"Durable execution record and usage",[885,1468,1469],{},"Business control flow",[870,1471,1472,1474,1478,1481],{},[885,1473,1445],{},[885,1475,1476],{},[814,1477,270],{"href":269},[885,1479,1480],{},"Duplicate business command\u002Feffect guard",[885,1482,1483],{},"Approval or workflow state",[859,1485,1487],{"id":1486},"shared-contracts","Shared contracts",[839,1489,1492],{"className":1490,"code":1491,"language":844,"meta":845},[842],"NormalizedMessage     Channel Gateway -> Front Door\nFrontDoorOutcome      Agno Front Door -> deterministic application code\nPlatformEvent         Producers -> EventRouter -> TriggerMatcher and Inngest\nStartRunCommand       Front Door \u002F Triggers \u002F API -> RunManager\nStartRunResult        RunManager -> every start caller; a closed outcome set\nPrincipal             Admission -> every action and context read\nAgentExecutionRequest AgentExecutor -> AgentRuntime\nAgentExecutionResult  AgentRuntime -> AgentExecutor\nExecutionOutcome      any executor -> RunManager\nRunResult             the durable product payload on the Run row\nToolSpec\u002FToolResult   Runtime \u003C-> Tool layer\nToolInvocation        Runtime -> Tool handler; the ambient identity of one call\nContextBrief          ContextBuilder -> AgentRuntime\nbound()               the one payload boundary; three payloads, three layers\nPolicyDecision        Policy -> RunManager \u002F ToolInvoker \u002F accrual caller\nRunEvent              Runtime\u002Frecorders -> SSE\u002FGateway\nResourceRef           everywhere a payload points at a row instead of carrying it\n",[830,1493,1491],{"__ignoreMap":845},[1495,1496,1498],"h3",{"id":1497},"resourceref",[830,1499,1500],{},"ResourceRef",[810,1502,1503],{},"It is the most shared type in the platform, so it is defined here and nowhere else.",[839,1505,1509],{"className":1506,"code":1507,"language":1508,"meta":845,"style":845},"language-python shiki shiki-themes github-dark","@dataclass(frozen=True)\nclass ResourceRef:\n    kind: str          # 'crm.company', 'prospect', 'knowledge_source', 'run'\n    id: str\n    label: str | None = None    # a human readable name, for a UI that must not join\n","python",[830,1510,1511,1518,1523,1528,1533],{"__ignoreMap":845},[1512,1513,1515],"span",{"class":1514,"line":22},"line",[1512,1516,1517],{},"@dataclass(frozen=True)\n",[1512,1519,1520],{"class":1514,"line":32},[1512,1521,1522],{},"class ResourceRef:\n",[1512,1524,1525],{"class":1514,"line":233},[1512,1526,1527],{},"    kind: str          # 'crm.company', 'prospect', 'knowledge_source', 'run'\n",[1512,1529,1530],{"class":1514,"line":244},[1512,1531,1532],{},"    id: str\n",[1512,1534,1535],{"class":1514,"line":264},[1512,1536,1537],{},"    label: str | None = None    # a human readable name, for a UI that must not join\n",[810,1539,1540,1541,1023,1544,1023,1547,1023,1550,1553,1554,1557],{},"It appears in ",[830,1542,1543],{},"RunResult.refs",[830,1545,1546],{},"ContextRequest.entities",[830,1548,1549],{},"ContextItem.ref",[830,1551,1552],{},"ContextBrief.items",", a truncated ",[830,1555,1556],{},"ToolResult",", and a stored idempotency response that was too large to keep.",[810,1559,1560],{},"Three rules keep it honest.",[1562,1563,1564,1574,1591],"ul",{},[1063,1565,1566,1569,1570,1573],{},[822,1567,1568],{},"A ref is a pointer, never a copy."," ",[830,1571,1572],{},"label"," exists so a list renders without a join, and it may be stale. Anything that must be current is re-read through the owning domain.",[1063,1575,1576,1582,1583,1586,1587,1590],{},[822,1577,1578,1581],{},[830,1579,1580],{},"kind"," is a registered string."," The owning resolver applies the store's tenant guard. Public service-key reads use ",[830,1584,1585],{},"scoped_db",". Agent-schema reads filter ",[830,1588,1589],{},"organization_id"," explicitly.",[1063,1592,1593,1596],{},[822,1594,1595],{},"A ref that does not resolve for a principal is dropped, not shown."," That is what stops a memory row naming a company from leaking its existence.",[1495,1598,1600],{"id":1599},"the-payload-boundary","The payload boundary",[810,1602,1603,1604,1606],{},"Three payloads are bounded, in three different layers, by one algorithm. It is defined here for the same reason ",[830,1605,1500],{}," is: written three times it becomes three algorithms, and the one that gets it wrong is silent.",[839,1608,1610],{"className":1506,"code":1609,"language":1508,"meta":845,"style":845},"Payload = dict | list\n\ndef bound(payload: Payload, limit_bytes: int) -> tuple[Payload, bool]:\n    \"\"\"Return the payload within the limit, and whether anything changed.\"\"\"\n",[830,1611,1612,1617,1623,1628],{"__ignoreMap":845},[1512,1613,1614],{"class":1514,"line":22},[1512,1615,1616],{},"Payload = dict | list\n",[1512,1618,1619],{"class":1514,"line":32},[1512,1620,1622],{"emptyLinePlaceholder":1621},true,"\n",[1512,1624,1625],{"class":1514,"line":233},[1512,1626,1627],{},"def bound(payload: Payload, limit_bytes: int) -> tuple[Payload, bool]:\n",[1512,1629,1630],{"class":1514,"line":244},[1512,1631,1632],{},"    \"\"\"Return the payload within the limit, and whether anything changed.\"\"\"\n",[810,1634,1635,1569,1638,1641,1642,1645,1646,1649,1650,1653],{},[822,1636,1637],{},"A top level list is a payload too, and it is the common one.",[830,1639,1640],{},"ToolResult.data"," is typed ",[830,1643,1644],{},"Any",", and a read tool answers with rows: ",[830,1647,1648],{},"crm.search"," returns a list of people. A signature that took a ",[830,1651,1652],{},"dict"," alone would force every caller to wrap, or to write the second implementation this function exists to prevent. Both shapes have top level items, and the algorithm below is the same for each. The return keeps the shape it was given, so a list never becomes an object.",[864,1655,1656,1669],{},[867,1657,1658],{},[870,1659,1660,1663,1666],{},[873,1661,1662],{},"Caller",[873,1664,1665],{},"Payload",[873,1667,1668],{},"Limit",[880,1670,1671,1685,1698],{},[870,1672,1673,1677,1682],{},[885,1674,1675],{},[830,1676,1050],{},[885,1678,1679],{},[830,1680,1681],{},"RunResult.output",[885,1683,1684],{},"32 KB",[870,1686,1687,1691,1696],{},[885,1688,1689],{},[830,1690,1234],{},[885,1692,1693],{},[830,1694,1695],{},"ToolResult.output",[885,1697,1684],{},[870,1699,1700,1705,1708],{},[885,1701,1702],{},[830,1703,1704],{},"SpanRecorder",[885,1706,1707],{},"span input and span output",[885,1709,1710],{},"8 KB",[810,1712,1713],{},[822,1714,1715,1716,1719],{},"Two payloads on ",[830,1717,1718],{},"agent.runs"," are refused rather than bounded, and both for one reason: a drop there is silent and it changes what the Run does.",[810,1721,1722,1723,1726,1727,837],{},"The ",[822,1724,1725],{},"snapshot"," is the first. Dropping a top level item removes the frozen tool contracts or the rendered skill text, and the Run then executes an agent that silently lost a tool it was published with. Nothing raises and no reader can tell. Validation refuses an oversized snapshot at publish, and the freeze fails the start. See ",[814,1728,1729],{"href":365},"runtime definitions",[810,1731,1732,1733,1738,1739,1741,1742,1745,1746,1748,1749,1751,1752,1755,1756,1758],{},"The Run's ",[822,1734,1735],{},[830,1736,1737],{},"input"," is the second, and it took the opposite answer until 2026-08-21. A trimmed ",[830,1740,1737],{}," is the caller's own instructions with the tail removed: the agent acts on part of a request and reports success, and ",[830,1743,1744],{},"RunResult.truncated"," describes the output rather than the input, so no field on the row records the loss. The rule this page already gives callers is the answer: a large payload passes a ",[830,1747,1500],{}," and leaves the body in the product table that owns it. So ",[830,1750,1050],{}," refuses the start with ",[830,1753,1754],{},"input_too_large"," instead of trimming it. Bounding it protected ",[830,1757,1718],{}," from a 5 MB trigger payload; refusing it protects the same table more strictly, and it protects the run as well.",[810,1760,1761],{},[822,1762,1763],{},"It drops whole items. It never cuts a structure.",[839,1765,1768],{"className":1766,"code":1767,"language":844,"meta":845},[842],"measure each top level item once, and count the envelope with them\n      │\n      ├─ the whole payload fits  -> return it unchanged, truncated = false\n      │\n      ├─ ANY item is over the limit ON ITS OWN\n      │      -> replace EVERY such item FIRST, before any drop\n      │      -> the whole value becomes one Dropped marker\n      │\n      └─ still over -> drop whole top level items from the tail\n                       until the running total fits, then serialize once to confirm\n",[830,1769,1767],{"__ignoreMap":845},[810,1771,1772,1775,1776,1779],{},[822,1773,1774],{},"Every oversized item is replaced, not the first one."," Take ",[830,1777,1778],{},"{'a': 40 KB, 'b': 40 KB}"," at 32 KB. Replace one and the second is still over the limit on its own, so the tail drop removes it whole and the caller loses a field it could have had a marker for. Both are replaced in the same pass, and the marker records what each one measured.",[810,1781,1782,1785,1786,1789,1790,1793,1794,1797],{},[822,1783,1784],{},"The replacement is the whole value, and the function never looks inside it."," A 40 KB ",[830,1787,1788],{},"rows"," becomes one ",[830,1791,1792],{},"Dropped"," marker. ",[830,1795,1796],{},"bound()"," reads one level, because a function that recurses has to decide how deep to go and every caller would get a different answer to that. A caller that wants its large field summarized rather than marked builds the summary before it calls.",[810,1799,1800,1775,1803,1806,1807,1033,1810,1813,1814,1816,1817,1819],{},[822,1801,1802],{},"An oversized item is replaced before anything is dropped, because otherwise the order of the keys decides the answer.",[830,1804,1805],{},"{'rows': 40 KB, 'summary': 1 KB, 'counts': 1 KB}",". Drop from the tail first and ",[830,1808,1809],{},"summary",[830,1811,1812],{},"counts"," go, ",[830,1815,1788],{}," alone is still over, and the caller keeps the one item it could not have used. Replace ",[830,1818,1788],{}," first and all three survive, two of them whole. A dict keeps insertion order, and no caller chooses that order, so a rule that reads the tail first returns a different payload for the same data.",[810,1821,1822,1825],{},[822,1823,1824],{},"Each item is measured once, not once per drop."," Re-serializing the whole payload after every drop is quadratic, and the case this function exists for is a read tool that answers with two thousand rows. Serialize each top level value once, keep a running total, drop from the tail against that total, and serialize the whole result once at the end to confirm the limit. One confirmation, not one per item.",[810,1827,1828,1831],{},[822,1829,1830],{},"The running total counts the envelope, or the confirmation fails on a wide payload."," The keys, the quotes, the commas and the braces are bytes the reader receives, and a dict of ten thousand short keys carries more of them than of values. Add each key and its separators to the total beside its value. The final serialize then confirms a limit the total already respected, and it never has to drop a second time. If it does exceed anyway, drop from the tail again and re-confirm: the loop is bounded by the item count, and reaching it means the envelope accounting is wrong.",[810,1833,1834,1835,1838,1839,1842,1843,1846,1847,1850,1851,1023,1853,1856,1857,1860,1861,837],{},"The second return value is ",[830,1836,1837],{},"true"," when ",[822,1840,1841],{},"anything changed",", a replacement as much as a drop. A 40 KB ",[830,1844,1845],{},"output"," reduced to one marker is not intact, and a flag that read ",[830,1848,1849],{},"false"," there would tell every reader it was. The caller sets its own field from it: ",[830,1852,1744],{},[830,1854,1855],{},"ToolResult.meta.truncated"," with ",[830,1858,1859],{},"meta.count"," kept honest, or ",[830,1862,1863],{},"span.attributes.truncated",[810,1865,1866,1569,1876,1878,1879,1882],{},[822,1867,1868,1869,1871,1872,1875],{},"A payload that is neither a ",[830,1870,1652],{}," nor a ",[830,1873,1874],{},"list"," is a caller error.",[830,1877,1796],{}," raises ",[830,1880,1881],{},"TypeError"," rather than wrapping it. Wrapping would change the shape the caller stores, which is the one promise this function makes.",[810,1884,1885,1892,1893,1895,1896,1898,1899,1902,1903,1905,1906,1908],{},[822,1886,1887,1889,1890,837],{},[830,1888,1796],{}," writes a marker, never a ",[830,1891,1500],{}," A ",[830,1894,1500],{}," names a row: it carries a ",[830,1897,1580],{}," and an ",[830,1900,1901],{},"id",", and it must resolve through the owning domain. ",[830,1904,1796],{}," is a pure function over a payload, and it has no row to point at. ",[830,1907,1681],{}," is free JSON, so there is often no row at all.",[839,1910,1912],{"className":1506,"code":1911,"language":1508,"meta":845,"style":845},"@dataclass(frozen=True)\nclass Dropped:\n    reason: Literal['too_large']\n    bytes: int                    # what the field measured before it was replaced\n",[830,1913,1914,1918,1923,1928],{"__ignoreMap":845},[1512,1915,1916],{"class":1514,"line":22},[1512,1917,1517],{},[1512,1919,1920],{"class":1514,"line":32},[1512,1921,1922],{},"class Dropped:\n",[1512,1924,1925],{"class":1514,"line":233},[1512,1926,1927],{},"    reason: Literal['too_large']\n",[1512,1929,1930],{"class":1514,"line":244},[1512,1931,1932],{},"    bytes: int                    # what the field measured before it was replaced\n",[810,1934,1935],{},[822,1936,1937],{},"It serializes under a sentinel key, because the payload it sits in is free JSON.",[839,1939,1943],{"className":1940,"code":1941,"language":1942,"meta":845,"style":845},"language-json shiki shiki-themes github-dark","{\"__dropped__\": {\"reason\": \"too_large\", \"bytes\": 40960}}\n","json",[830,1944,1945],{"__ignoreMap":845},[1512,1946,1947,1951,1955,1958,1961,1964,1968,1970,1973,1975,1978],{"class":1514,"line":22},[1512,1948,1950],{"class":1949},"s95oV","{",[1512,1952,1954],{"class":1953},"sDLfK","\"__dropped__\"",[1512,1956,1957],{"class":1949},": {",[1512,1959,1960],{"class":1953},"\"reason\"",[1512,1962,1963],{"class":1949},": ",[1512,1965,1967],{"class":1966},"sU2Wk","\"too_large\"",[1512,1969,1023],{"class":1949},[1512,1971,1972],{"class":1953},"\"bytes\"",[1512,1974,1963],{"class":1949},[1512,1976,1977],{"class":1953},"40960",[1512,1979,1980],{"class":1949},"}}\n",[810,1982,1983,1984,1987,1988,1991,1992,1995,1996,1998,1999,2001,2002,2004],{},"A bare ",[830,1985,1986],{},"{\"reason\": \"too_large\", \"bytes\": 40960}"," is a body a real tool could return, so a reader could not tell a marker from data. ",[830,1989,1990],{},"__dropped__"," is a key no caller writes, and one lookup finds it. The marker keeps the shape and the size honest, and it parses. A caller that ",[822,1993,1994],{},"does"," own the row substitutes a ",[830,1997,1500],{}," for the marker afterwards: ",[830,2000,1234],{}," does this, because a tool knows the rows it read. ",[830,2003,1050],{}," does not, so a Run keeps the marker. One function, one rule, and the ref stays with the layer that can resolve it.",[810,2006,2007,2010,2011,1033,2014,2017,2018,2021],{},[822,2008,2009],{},"Serialize with the same encoder the write uses."," A payload holds ",[830,2012,2013],{},"UUID",[830,2015,2016],{},"datetime"," values that plain ",[830,2019,2020],{},"json.dumps"," refuses, and an encoder that differs from the one the database client uses measures a different number of bytes than the reader receives.",[810,2023,2024,2027,2028,2031],{},[822,2025,2026],{},"A truncated JSON body is worse than a short one",", and that is the whole reason this is a function rather than a convention. ",[830,2029,2030],{},"json.dumps(payload)[:32768]"," satisfies the limit and produces a body no reader can parse. It looks correct in review and it fails at the reader, which is late.",[810,2033,2034],{},"Two rules travel with it.",[1562,2036,2037],{},[1063,2038,2039,2042],{},[822,2040,2041],{},"Measure the serialized bytes, not the object."," The limit is what a reader receives.",[810,2044,2045,2046,2049,2050,2053,2054,1033,2056,2058,2059,2062],{},"A second size limit sits beside this one and is easy to meet by accident: a PostgREST filter travels in the URL, and Kong refuses a request line over 8 KB. One ",[830,2047,2048],{},"in.()"," list therefore holds about 220 UUIDs. Any set that grows with a Run tree is filtered by a denormalized ",[830,2051,2052],{},"root_run_id"," instead, which is why ",[830,2055,1004],{},[830,2057,977],{}," both carry that column, and why ",[830,2060,2061],{},"ai_usage_log"," is stamped with it. See invariant 38.",[1562,2064,2065],{},[1063,2066,2067,2070,2071,2074,2075,2077],{},[822,2068,2069],{},"Redaction runs before bounding, never after."," Bounding drops items; a credential in a dropped item would be removed by luck rather than by rule. The ",[814,2072,2073],{"href":190},"tool layer"," owns the redaction step, and ",[814,2076,209],{"href":277}," relies on it having already run.",[1495,2079,2081],{"id":2080},"runsource",[830,2082,2083],{},"RunSource",[839,2085,2087],{"className":1506,"code":2086,"language":1508,"meta":845,"style":845},"@dataclass(frozen=True)\nclass RunSource:\n    kind: Literal['front_door', 'trigger', 'api', 'workflow_step']\n    trigger_id: UUID | None = None\n    parent_span_id: UUID | None = None    # set for workflow_step\n\n    @classmethod\n    def front_door(cls) -> 'RunSource': ...\n    @classmethod\n    def trigger(cls, trigger_id: UUID) -> 'RunSource': ...\n",[830,2088,2089,2093,2098,2103,2108,2113,2117,2122,2127,2131],{"__ignoreMap":845},[1512,2090,2091],{"class":1514,"line":22},[1512,2092,1517],{},[1512,2094,2095],{"class":1514,"line":32},[1512,2096,2097],{},"class RunSource:\n",[1512,2099,2100],{"class":1514,"line":233},[1512,2101,2102],{},"    kind: Literal['front_door', 'trigger', 'api', 'workflow_step']\n",[1512,2104,2105],{"class":1514,"line":244},[1512,2106,2107],{},"    trigger_id: UUID | None = None\n",[1512,2109,2110],{"class":1514,"line":264},[1512,2111,2112],{},"    parent_span_id: UUID | None = None    # set for workflow_step\n",[1512,2114,2115],{"class":1514,"line":222},[1512,2116,1622],{"emptyLinePlaceholder":1621},[1512,2118,2119],{"class":1514,"line":360},[1512,2120,2121],{},"    @classmethod\n",[1512,2123,2124],{"class":1514,"line":368},[1512,2125,2126],{},"    def front_door(cls) -> 'RunSource': ...\n",[1512,2128,2129],{"class":1514,"line":375},[1512,2130,2121],{},[1512,2132,2133],{"class":1514,"line":157},[1512,2134,2135],{},"    def trigger(cls, trigger_id: UUID) -> 'RunSource': ...\n",[810,2137,2138,2139,2142,2143,2145,2146,2149,2150,2152,2153,2156,2157,837],{},"The Inngest lane follows the ",[822,2140,2141],{},"actor kind",", not ",[830,2144,2083],{}," alone. An interactive user actor on ",[830,2147,2148],{},"front_door"," or ",[830,2151,254],{}," is interactive; a machine actor and every ",[830,2154,2155],{},"workflow_step"," child are batch. See ",[814,2158,2159],{"href":372},"runtime execution",[859,2161,2163],{"id":2162},"naming-rules","Naming rules",[810,2165,2166],{},"Three words are load bearing across every page, and each has exactly one meaning.",[864,2168,2169,2182],{},[867,2170,2171],{},[870,2172,2173,2176,2179],{},[873,2174,2175],{},"Word",[873,2177,2178],{},"Means",[873,2180,2181],{},"Never means",[880,2183,2184,2205,2227],{},[870,2185,2186,2190,2202],{},[885,2187,2188],{},[822,2189,184],{},[885,2191,2192,2193,1023,2196,1023,2199],{},"what a model may know: ",[830,2194,2195],{},"ContextBrief",[830,2197,2198],{},"ContextPolicy",[830,2200,2201],{},"ContextSource",[885,2203,2204],{},"ambient execution identity, which has accessors and no noun",[870,2206,2207,2212,2224],{},[885,2208,2209],{},[822,2210,2211],{},"state",[885,2213,2214,2215,1023,2218,2149,2221],{},"configuration lifecycle: a definition is ",[830,2216,2217],{},"draft",[830,2219,2220],{},"active",[830,2222,2223],{},"disabled",[885,2225,2226],{},"execution lifecycle",[870,2228,2229,2234,2254],{},[885,2230,2231],{},[822,2232,2233],{},"status",[885,2235,2236,2237,2240,2241,2244,2245,1023,2248,2149,2251],{},"execution lifecycle: a Run is ",[830,2238,2239],{},"queued"," … ",[830,2242,2243],{},"cancelled","; a span is ",[830,2246,2247],{},"running",[830,2249,2250],{},"ok",[830,2252,2253],{},"error",[885,2255,2256],{},"configuration lifecycle",[810,2258,2259],{},"Two more, so a grep returns one subsystem.",[1562,2261,2262,2274],{},[1063,2263,2264,2269,2270,2273],{},[822,2265,2266],{},[830,2267,2268],{},"scope"," belongs to policy. It is one exact action name in ",[830,2271,2272],{},"Principal.scopes",". Nothing else is called a scope.",[1063,2275,2276,2281,2282,2285,2286,1023,2289,1023,2292,1033,2295,837],{},[822,2277,2278],{},[830,2279,2280],{},"Event"," is never a bare type name. The platform envelope is ",[830,2283,2284],{},"PlatformEvent",", and the qualified siblings are ",[830,2287,2288],{},"InboundEvent",[830,2290,2291],{},"RunEvent",[830,2293,2294],{},"ConversationEvent",[830,2296,2297],{},"InngestEvent",[859,2299,2301],{"id":2300},"product-state-vs-infrastructure-state","Product state vs infrastructure state",[810,2303,2304],{},"AgencyCore product state is stable and readable by the product:",[839,2306,2309],{"className":2307,"code":2308,"language":844,"meta":845},[842],"Run status:     queued | running | waiting | succeeded | failed | cancelled\nRun waiting_on: approval | event | delay      null unless status is waiting\n",[830,2310,2308],{"__ignoreMap":845},[810,2312,2313],{},"Inngest attempt IDs, worker retries, queue state and Connect transport state are infrastructure telemetry. Keep them as correlation fields, not the product lifecycle API.",[859,2315,2317],{"id":2316},"definitions-and-run-snapshot","Definitions and Run snapshot",[810,2319,2320],{},"Definitions use:",[839,2322,2325],{"className":2323,"code":2324,"language":844,"meta":845},[842],"Draft config -> validate -> published config\n",[830,2326,2324],{"__ignoreMap":845},[810,2328,2329,2330,2333],{},"There is ",[822,2331,2332],{},"no definition revision\u002Fhistory subsystem in V1",". Before dispatch the Run freezes the effective execution snapshot:",[839,2335,2338],{"className":2336,"code":2337,"language":844,"meta":845},[842],"Frozen in Run.snapshot\n  published definition config\n  rendered Skill content\n  model-facing Tool contracts\n  ContextPolicy\n  model configuration\n\nFrozen on the Run row, in its own column\n  principal grant           agent.runs.principal\n\nRead live at checkpoints\u002Fexecution\n  Tool enabled\u002Fdisabled kill switch\n  Policy rules\n  the actor's current rights, narrowing the frozen grant\n  credentials \u002F connection status\n  handler implementation\n  business data and retrieved context\n",[830,2339,2337],{"__ignoreMap":845},[810,2341,2342],{},"This keeps work stable while allowing emergency policy\u002Ftool revocation to take effect immediately.",[810,2344,2345,2346,2349,2350,2352,2353,2356,2357,2360],{},"The principal grant is frozen too, and it is ",[822,2347,2348],{},"not"," inside ",[830,2351,1725],{},". ",[830,2354,2355],{},"agent.runs.principal"," is its own column and ",[830,2358,2359],{},"PrincipalFactory"," is its one writer. One fact with two homes disagrees with itself the first time either writer changes.",[810,2362,2363,1569,2369,1033,2372,2374],{},[822,2364,2365,2366,2368],{},"A ",[830,2367,2223],{}," definition refuses a new Run tree, and not a child of a tree already running.",[830,2370,2371],{},"assert_run_shape()",[830,2373,1050],{}," must hold the same asymmetry, because the trigger fires after the manager and never sees a start the manager already refused.",[810,2376,2377,2380,2381,2384,2385,837],{},[822,2378,2379],{},"A definition references definitions of its own organization only."," A platform template is forked before it is referenced, exactly as it is forked before it is run. ",[830,2382,2383],{},"runs_definition_fk"," already pairs a Run with a definition of its own organization, so the reference rule and the execution rule now say the same thing, and the reverse lookup that four definition rules depend on stays answerable inside one tenant. See ",[814,2386,1729],{"href":365},[859,2388,2390],{"id":2389},"coexistence-with-the-live-agent-stack","Coexistence with the live agent stack",[810,2392,2393,2394,2397,2398,2401],{},"This platform is built ",[822,2395,2396],{},"beside"," the current agent stack, not on top of it. The live production stack remains the fallback until Phase 9 cutover.\nThis is a deployment boundary, not a guarantee that every legacy module remains on ",[830,2399,2400],{},"agentic-platform"," trunk.\nThe trunk already removes legacy chat surfaces; compare new work with trunk, not staging.",[810,2403,2404],{},"Three rules make that separation real rather than aspirational.",[1060,2406,2407,2647,2671],{},[1063,2408,2409,2416,2417,2420,2421,2423,2424,2427,2428,1033,2430,2432,2433,2436,2437,2570,2572,2580,2581,837,2583,2585,2586,1033,2589,2592,2593,2595,2596,2599,2600,2602,2603,2606,2607,2609,2610,837,2613,2615,1569,2622,2625,2626,2628,2629,2631,2632,2634,2635,2638,2639,2642,2643,2646],{},[822,2410,2411,2412,2415],{},"Every platform table lives in the ",[830,2413,2414],{},"agent"," Postgres schema."," The old runtime owns ",[830,2418,2419],{},"public.agent_runs",", so the word ",[830,2422,2414],{}," is taken inside ",[830,2425,2426],{},"public"," but free as a schema. ",[830,2429,1718],{},[830,2431,2419],{}," are different tables and cannot collide, so the separation is structural rather than a naming convention someone must remember. It also survives cutover: when the old stack is deleted, nothing is renamed, because no name was ever a workaround.",[2434,2435],"br",{},"Four consequences follow, and each has bitten a project that skipped it.",[1562,2438,2439,2479,2498,2551],{},[1063,2440,2441,1569,2444,2447,2448,1023,2450,1033,2452,2454,2455,2458,2459,1023,2462,1033,2465,2468,2469,2472,2473,2476,2477,837],{},[822,2442,2443],{},"A new schema starts with no privileges.",[830,2445,2446],{},"pg_default_acl"," carries grants for ",[830,2449,2426],{},[830,2451,226],{},[830,2453,409],{}," only. The creating migration must ",[830,2456,2457],{},"GRANT USAGE ON SCHEMA agent"," to ",[830,2460,2461],{},"anon",[830,2463,2464],{},"authenticated",[830,2466,2467],{},"service_role",", and set ",[830,2470,2471],{},"ALTER DEFAULT PRIVILEGES",", or PostgREST answers ",[830,2474,2475],{},"permission denied"," while every RLS policy is correct. RLS stays the tenancy boundary exactly as it is in ",[830,2478,2426],{},[1063,2480,2481,2484,2485,2488,2489,2492,2493,2497],{},[822,2482,2483],{},"The schema must be exposed to PostgREST per environment."," Local is ",[830,2486,2487],{},"[api] schemas"," in ",[830,2490,2491],{},"supabase\u002Fconfig.toml",". Staging and production are a Supabase Dashboard change, and it must land ",[2494,2495,2496],"em",{},"before"," that environment applies the migration.",[1063,2499,2500,1569,2503,1033,2506,2509,2510,2512,2513,2516,2517,2520,2521,2532,2533,2536,2537,2539,2540,2543,2544,1033,2547,2550],{},[822,2501,2502],{},"The client must ask for the schema, and it must ask once.",[830,2504,2505],{},"supabase-py",[830,2507,2508],{},"supabase-js"," default to ",[830,2511,2426],{},". In ",[830,2514,2515],{},"supabase-py 2.18.1"," a ",[830,2518,2519],{},".schema(\"agent\")"," call ",[822,2522,2523,2524,2527,2528,2531],{},"builds a new ",[830,2525,2526],{},"AsyncPostgrestClient"," with its own ",[830,2529,2530],{},"httpx"," session",", and nothing closes it, so calling it per request leaks a connection pool per request. ",[830,2534,2535],{},"ac-python-api"," therefore holds one cached ",[830,2538,2414],{},"-schema client in ",[830,2541,2542],{},"src\u002Fcore\u002Fdatabase.py",", beside the admin client and with the same thread-local lifetime, and every caller reads that accessor. The client sets ",[830,2545,2546],{},"Accept-Profile",[830,2548,2549],{},"Content-Profile"," together, so one accessor serves reads and writes.",[1063,2552,2553,2556,2557,2559,2560,2562,2563,2565,2566,2569],{},[822,2554,2555],{},"Every write is service-role."," No ",[830,2558,2414],{}," table carries an insert, update or delete RLS policy: ",[830,2561,2464],{}," reads its own organization and writes nothing. So a platform writer takes the admin client, never the org-scoped one. This is the opposite of the house pattern in ",[830,2564,2426],{},", and it fails silently in the dangerous direction — RLS filters a write rather than raising, so an org-scoped ",[830,2567,2568],{},"UPDATE"," returns success and changes no row.",[2434,2571],{},[822,2573,2574,2575,2579],{},"A platform table is a table that ",[814,2576,2578],{"href":2577},"#data-model","Data model"," names."," Every other table is product state, and product state stays in ",[830,2582,2426],{},[2434,2584],{},"Product state that joins to ",[830,2587,2588],{},"public.intel_*",[830,2590,2591],{},"public.crm_*"," gains nothing from the isolation. The name does not collide. The joins the table reads on every query stay inside one schema. The exposure change above is not needed. So the table keeps the house pattern: an ",[830,2594,1589],{}," column, RLS on all four verbs, and an entry in ",[830,2597,2598],{},"ORG_SCOPED_TABLES",". The Signals Search prospect tables are the first of these.",[2434,2601],{},"A column that names the Run which produced the row is the one reference that crosses. It carries no foreign key, exactly as ",[830,2604,2605],{},"ai_usage_log.agent_root_run_id"," does, because a real key ties a ",[830,2608,2426],{}," table back into the isolated schema. See ",[814,2611,2612],{"href":277},"observability and operations",[2434,2614],{},[822,2616,2617,2618,2621],{},"A product table takes ",[830,2619,2620],{},"scoped_db(organization_id)",", and this is the mirror of the service-role bullet.",[830,2623,2624],{},"OrgScopedClient"," adds the organization filter for a table in ",[830,2627,2598],{},". The admin client adds none, so an ",[830,2630,2568],{}," sent through it reaches every organization and reports success. Each client is silently wrong on the other kind of table, in the opposite direction.",[2434,2633],{},"Check a name against the live catalog, never against the migration files: ",[830,2636,2637],{},"agent_runs"," was created by a ",[830,2640,2641],{},"RENAME",", so a ",[830,2644,2645],{},"CREATE TABLE"," grep reports it as free.",[1063,2648,2649,2655,2656,2659,2660,2662,2663,2666,2667,2670],{},[822,2650,2651,2652,837],{},"Every platform endpoint sits under ",[830,2653,2654],{},"\u002Fapi\u002Fv1\u002Fagentic\u002F"," The live ",[830,2657,2658],{},"\u002Fapi\u002Fv1\u002Fagents\u002Fruns"," is driven by the ",[830,2661,832],{}," CLI, and two paths one word apart would be a support burden, so the start boundary is ",[830,2664,2665],{},"\u002Fapi\u002Fv1\u002Fagentic\u002Fruns",". The segment then covers the whole surface layer, and not that one route. Most other platform paths are free today, so a per-route decision is possible. It is refused for three reasons. The prefix is what a reader greps to see the boundary the other two rules draw. It is one entry in ",[830,2668,2669],{},"ac-cli\u002Fscripts\u002Faudit_endpoints.py"," rather than one entry per surface. And each of the seven surfaces would otherwise answer the same question again, which is how a mixed scheme arrives.",[1063,2672,2673,2676,2677,2680,2681,2684,2685,1023,2688,1023,2691,1023,2694,1023,2697,2149,2700,2703,2704,2706,2707,2710,2711,2713],{},[822,2674,2675],{},"New code never imports the old stack."," An import-linter contract in ",[830,2678,2679],{},"ac-python-api\u002Fpyproject.toml"," forbids ",[830,2682,2683],{},"src.agentic"," from importing ",[830,2686,2687],{},"src.workflow_engine",[830,2689,2690],{},"src.agent_runtime",[830,2692,2693],{},"src.agents",[830,2695,2696],{},"src.domains.envoy",[830,2698,2699],{},"src.domains.chat",[830,2701,2702],{},"src.domains.workflows",". One import across that line and the fallback stops being real, which is why it is a CI contract and not a sentence here. The contract is directional. A composition root outside ",[830,2705,2683],{}," may import both sides, which is how one worker process serves both Inngest apps, and ",[830,2708,2709],{},"src\u002Fcore\u002Finngest_worker.py"," is that root. A module inside ",[830,2712,2683],{}," may not.",[810,2715,2716,2722,2723,1033,2725,2727,2728,2730,2731,2733],{},[822,2717,2718,2721],{},[830,2719,2720],{},"agentic"," survives in two places, and only two."," A Postgres schema solves the table namespace. Python packages and URL paths have no equivalent, and ",[830,2724,2693],{},[830,2726,2658],{}," are both taken by the live stack. So the module root stays ",[830,2729,2683],{}," and the endpoint prefix stays ",[830,2732,2654],{},". Tables do not, because they had a better option.",[810,2735,2736],{},"The contract is deleted in the cutover phase, when there is nothing left to isolate from.",[859,2738,2740],{"id":2739},"deployment-topology","Deployment topology",[810,2742,2743],{},"Two processes, and the split is a rule rather than a tuning choice.",[864,2745,2746,2758],{},[867,2747,2748],{},[870,2749,2750,2753,2755],{},[873,2751,2752],{},"Process",[873,2754,1273],{},[873,2756,2757],{},"Never does",[880,2759,2760,2776],{},[870,2761,2762,2767,2773],{},[885,2763,2764],{},[822,2765,2766],{},"Web dyno",[885,2768,2769,2770,2772],{},"The synchronous control plane: the HTTP API, validation, ",[830,2771,1205],{},", and sending events",[885,2774,2775],{},"Execute an Inngest function",[870,2777,2778,2783,2786],{},[885,2779,2780],{},[822,2781,2782],{},"Worker dyno",[885,2784,2785],{},"All durable execution: every Inngest function, over an Inngest Connect session",[885,2787,2788],{},"Serve HTTP",[810,2790,2791,2794],{},[822,2792,2793],{},"If it is an Inngest function, it runs on the worker."," There is no short-function exemption. A reaper that finishes in 200 milliseconds runs on the worker for the same reason a long agent task does: one place to look, one set of limits, one restart story. The moment the topology depends on how long a function takes, every new function needs that judgement made again, and eventually it is made wrong.",[810,2796,2797,2798,2801],{},"The worker holds a ",[822,2799,2800],{},"persistent outbound WebSocket"," to Inngest, which has three consequences worth stating.",[1562,2803,2804,2815,2818],{},[1063,2805,2806,2807,2810,2811,2814],{},"There is no public ",[830,2808,2809],{},"\u002Fapi\u002Finngest"," endpoint, and no inbound request to verify. ",[830,2812,2813],{},"INNGEST_SIGNING_KEY"," stays, as the credential that opens the connection rather than the key that signs a request.",[1063,2816,2817],{},"No HTTP timeout bounds a step. The step budget belongs to the worker, not to a router.",[1063,2819,2820],{},"Connect needs a long lived process, so it does not work on serverless. A dyno is the right shape.",[1495,2822,2824],{"id":2823},"one-session-two-apps","One session, two apps",[810,2826,2827,2828,2831],{},"The live stack's 21 Inngest functions move to the worker in Phase 1. They do not stay on ",[830,2829,2830],{},"inngest.fast_api.serve"," until cutover. Leaving them there would run two execution paths side by side for the whole build, and the rule above exists to stop exactly that: once the topology has two paths, every new function needs the judgement made again.",[810,2833,2834,2835,2838,2839,2842],{},"One process holds one WebSocket and registers two Inngest apps, because ",[830,2836,2837],{},"connect(apps=[...])"," takes a list of ",[830,2840,2841],{},"(client, functions)"," pairs.",[864,2844,2845,2855],{},[867,2846,2847],{},[870,2848,2849,2852],{},[873,2850,2851],{},"App id",[873,2853,2854],{},"Carries",[880,2856,2857,2867],{},[870,2858,2859,2864],{},[885,2860,2861],{},[830,2862,2863],{},"agencycore-api",[885,2865,2866],{},"The 21 live functions, unchanged.",[870,2868,2869,2874],{},[885,2870,2871],{},[830,2872,2873],{},"agencycore-agentic",[885,2875,2876],{},"The new platform functions.",[810,2878,2879,1569,2882,2885,2886,2888,2889,2892],{},[822,2880,2881],{},"A function's Inngest id embeds its app id.",[830,2883,2884],{},"agent.run"," under ",[830,2887,2863],{}," is ",[830,2890,2891],{},"agencycore-api-agent.run",". So the app id is part of the function's identity, and three rules follow from that one fact.",[1562,2894,2895,2898,2901],{},[1063,2896,2897],{},"The live app keeps the id it already has in Inngest Cloud. Renaming it renames all 21 functions and orphans every in-flight run.",[1063,2899,2900],{},"The split into two apps is decided now or not at all. Merging later, or splitting later, renames every function that moves.",[1063,2902,2903],{},"The ids therefore merge at cutover only by deleting the live app, never by moving its functions into the other one.",[810,2905,2906,1569,2909,1878,2912,2915,2916,2919,2920,2923],{},[822,2907,2908],{},"Every registered app carries at least one function.",[830,2910,2911],{},"connect()",[830,2913,2914],{},"FunctionConfigInvalidError: no functions found"," when an app's list is empty, and it raises during construction, so an empty app is a boot crash rather than a degraded worker. The new app therefore ships ",[830,2917,2918],{},"agentic.healthcheck"," from its first commit. That function also replaces ",[830,2921,2922],{},"GET \u002Fapi\u002Finngest"," as the \"is the worker alive\" probe, which the topology no longer has.",[1495,2925,2927],{"id":2926},"what-the-worker-owes-on-shutdown","What the worker owes on shutdown",[810,2929,2930,2931,2934,2935,2938],{},"The platform sends ",[830,2932,2933],{},"SIGTERM",", and the Connect session then ",[822,2936,2937],{},"waits for the in-flight step to finish"," before it closes. That is the whole guarantee, and two limits sit around it.",[1562,2940,2941,2950],{},[1063,2942,2943,2946,2947,2949],{},[822,2944,2945],{},"The platform's own kill deadline bounds the drain."," On Heroku that is 30 seconds after ",[830,2948,2933],{},". A step that runs longer is killed mid-flight. Completed steps stay memoized, so the run resumes at the first unfinished step. A completed matching Tool claim returns its stored result. An interrupted claim keeps its lease and vendor recovery rules. Measured: re-dispatch after a kill takes roughly two minutes.",[1063,2951,2952,1569,2955,2958,2959,2962,2963,2966,2967,2969],{},[822,2953,2954],{},"No process supervisor may shorten that window.",[830,2956,2957],{},"honcho"," cannot run the worker, because it sends ",[830,2960,2961],{},"SIGKILL"," five seconds after its ",[2494,2964,2965],{},"first"," child exits, whatever the platform allows. Celery drains in about a second, so the Inngest worker would get about six. A supervisor for this dyno forwards ",[830,2968,2933],{}," to every child and then waits for all of them.",[810,2971,2972,2975],{},[830,2973,2974],{},"max_worker_concurrency"," is set explicitly. Function-level concurrency is keyed per organization, so the total scales with the number of organizations, and several functions declare no limit at all. It is the only global limit the worker has.",[859,2977,2578],{"id":612},[810,2979,2980,2981,2983,2984,2988,2989,2991,2992,1033,2994,2997],{},"Every table below lives in the ",[830,2982,2414],{}," Postgres schema, per rule 1 of ",[814,2985,2987],{"href":2986},"#coexistence-with-the-live-agent-stack","coexistence",". Existing production tables stay in ",[830,2990,2426],{}," and are reused where noted by the detailed docs; ",[830,2993,2061],{},[830,2995,2996],{},"ai_usage_daily"," are the ones that matter here.",[864,2999,3000,3010],{},[867,3001,3002],{},[870,3003,3004,3007],{},[873,3005,3006],{},"Table",[873,3008,3009],{},"Holds",[880,3011,3012,3024,3034,3043,3053,3063,3072,3082,3092,3102,3112,3122,3132,3142,3152,3165,3178,3188],{},[870,3013,3014,3019],{},[885,3015,3016],{},[830,3017,3018],{},"agent.definitions",[885,3020,3021,3022],{},"Agent, Workflow and Skill draft + published config, keyed by ",[830,3023,1580],{},[870,3025,3026,3031],{},[885,3027,3028],{},[830,3029,3030],{},"agent.triggers",[885,3032,3033],{},"Event pattern\u002Ffilter\u002Ftarget\u002Finput template\u002Fconfig",[870,3035,3036,3040],{},[885,3037,3038],{},[830,3039,1718],{},[885,3041,3042],{},"Every product execution + immutable execution snapshot",[870,3044,3045,3050],{},[885,3046,3047],{},[830,3048,3049],{},"agent.run_control",[885,3051,3052],{},"The cancellation request for one Run",[870,3054,3055,3060],{},[885,3056,3057],{},[830,3058,3059],{},"agent.sessions",[885,3061,3062],{},"The Agno message history for one agent Run, across segments",[870,3064,3065,3069],{},[885,3066,3067],{},[830,3068,977],{},[885,3070,3071],{},"Pending\u002Fresolved human decisions",[870,3073,3074,3079],{},[885,3075,3076],{},[830,3077,3078],{},"agent.tools",[885,3080,3081],{},"Model-facing Tool catalogue",[870,3083,3084,3089],{},[885,3085,3086],{},[830,3087,3088],{},"agent.memories",[885,3090,3091],{},"Durable preference\u002Fobservation with provenance",[870,3093,3094,3099],{},[885,3095,3096],{},[830,3097,3098],{},"agent.knowledge_sources",[885,3100,3101],{},"Platform\u002Forganization document, upload or sync source",[870,3103,3104,3109],{},[885,3105,3106],{},[830,3107,3108],{},"agent.knowledge_chunks",[885,3110,3111],{},"Chunk text + embedding, with the embedding model pinned per row",[870,3113,3114,3119],{},[885,3115,3116],{},[830,3117,3118],{},"agent.policies",[885,3120,3121],{},"Action\u002Fcheckpoint rule",[870,3123,3124,3129],{},[885,3125,3126],{},[830,3127,3128],{},"agent.cost_ceilings",[885,3130,3131],{},"Cost ceilings. Rate and concurrency live in Inngest; count ceilings live in the definition budget",[870,3133,3134,3139],{},[885,3135,3136],{},[830,3137,3138],{},"agent.policy_decisions",[885,3140,3141],{},"Every admission decision, and every decision that refused, gated or stopped work",[870,3143,3144,3149],{},[885,3145,3146],{},[830,3147,3148],{},"agent.provider_jobs",[885,3150,3151],{},"One asynchronous provider job: the tenant, the run tree, the submit span, the vendor job id, the state, the result and the settled cost",[870,3153,3154,3159],{},[885,3155,3156],{},[830,3157,3158],{},"agent.idempotency_keys",[885,3160,3161,3162,3164],{},"Durable Tool and webhook effect claims and stored results. It is also the Tool replay journal. A Run start is not in it: ",[830,3163,1718],{}," carries its own start key",[870,3166,3167,3171],{},[885,3168,3169],{},[830,3170,1004],{},[885,3172,3173,3174,1033,3176],{},"One unit of work inside a Run, carrying ",[830,3175,1589],{},[830,3177,2052],{},[870,3179,3180,3185],{},[885,3181,3182],{},[830,3183,3184],{},"agent.conversations",[885,3186,3187],{},"Platform conversation: organization, creator, title, summary, last activity",[870,3189,3190,3195],{},[885,3191,3192],{},[830,3193,3194],{},"agent.conversation_messages",[885,3196,3197,3198,3201],{},"Role, sender, text, attachment count, originating ",[830,3199,3200],{},"run_id"," when one exists",[810,3203,3204],{},"Remote channel install tables and MCP connection tables stay deferred. The current web-first slice does not add them to the schema.",[810,3206,3207,3209,3210,3212,3213,3215,3216,3219,3220,837],{},[830,3208,2061],{}," \u002F ",[830,3211,2996],{}," remain the cost truth; spans point at usage rows instead of storing a second price. ",[830,3214,2061],{}," gains one column, ",[830,3217,3218],{},"agent_root_run_id",", so a tree total is one indexed aggregate rather than a filter built from the span tree. See ",[814,3221,2612],{"href":277},[859,3223,3225],{"id":3224},"not-building-in-v1","Not building in V1",[1562,3227,3228,3231,3234,3237,3243,3246,3249,3252,3255,3258,3261,3264,3271,3274,3277,3280,3283,3289,3292,3295,3298,3301,3307,3313],{},[1063,3229,3230],{},"A second agent runtime or backend selector.",[1063,3232,3233],{},"Claude\u002Fmanaged-agent execution as a target backend.",[1063,3235,3236],{},"Agno Teams, Agno workflows, AgentOS approvals or Agno background lifecycle as product primitives.",[1063,3238,3239,3240,837],{},"Arbitrary workflow code, loops or dynamic fan-out. A constrained visual editor over the same eight node types is in scope. See ",[814,3241,3242],{"href":357},"workflow visualizer",[1063,3244,3245],{},"A custom scheduler, queue, workflow engine or durable checkpoint system.",[1063,3247,3248],{},"A general policy language such as arbitrary Python\u002FSQL\u002FRego\u002FCEL.",[1063,3250,3251],{},"A permission table duplicating user roles and Agent tool grants.",[1063,3253,3254],{},"A second rate limiter or second cost meter.",[1063,3256,3257],{},"A retrieval Agent.",[1063,3259,3260],{},"A vector database separate from Postgres\u002Fpgvector.",[1063,3262,3263],{},"A separate store for working or episodic memory.",[1063,3265,3266,3267,3270],{},"Direct database access or generic ",[830,3268,3269],{},"api_request"," Tools for Agents.",[1063,3272,3273],{},"A channel-specific Agent or prompt.",[1063,3275,3276],{},"Email inside Channel Gateway.",[1063,3278,3279],{},"Conversation attachments. A file enters as an organization knowledge source, never through a chat.",[1063,3281,3282],{},"A Telegram or WhatsApp adapter in V1.",[1063,3284,3285,3286,3288],{},"An interactive channel as a ",[830,3287,2284],{}," producer.",[1063,3290,3291],{},"A durable event table beside Run spans.",[1063,3293,3294],{},"A replay log for SSE in V1; reconnect by refetching durable state.",[1063,3296,3297],{},"Definition revision\u002Fhistory\u002Frollback UI in V1.",[1063,3299,3300],{},"Run steering. Cancel and restart covers V1.",[1063,3302,2365,3303,3306],{},[830,3304,3305],{},"phase"," enum beside the Run status.",[1063,3308,3309,3310,3312],{},"An index of which Runs wait for which event; the wait node carries its own correlation. ",[830,3311,3148],{}," is not that index: it is the durable state of one external job, and the Run it names is the tree the cost belongs to. A wait on a provider job still declares its own correlation.",[1063,3314,3315],{},"A notification system for approvals; one outbound intent covers V1.",[859,3317,3319],{"id":3318},"cross-document-invariants","Cross-document invariants",[810,3321,3322],{},"Before merging any future design update, verify:",[1060,3324,3325,3328,3333,3339,3344,3347,3350,3353,3356,3359,3362,3368,3375,3378,3387,3399,3402,3414,3420,3429,3432,3435,3450,3453,3456,3462,3465,3471,3474,3477,3483,3489,3497,3523,3530,3536,3539,3546,3552,3558,3561,3564,3567,3570,3573],{},[1063,3326,3327],{},"Front Door and Triggers still call the same Run start boundary.",[1063,3329,3330,3332],{},[830,3331,1050],{}," is the only product Run lifecycle owner.",[1063,3334,3335,3336,3338],{},"Agno is hidden behind ",[830,3337,950],{},"; no Agno type leaks into policy, tools, definitions or surfaces.",[1063,3340,3341,3342,837],{},"Every Agent action still goes through ",[830,3343,1234],{},[1063,3345,3346],{},"Tool write\u002Fsend paths still use Idempotency.",[1063,3348,3349],{},"Policy is live at the next checkpoint and does not become Agent prompt logic.",[1063,3351,3352],{},"Email remains Nylas\u002Ftool\u002Ftrigger-owned.",[1063,3354,3355],{},"Definition edits do not mutate in-flight Runs.",[1063,3357,3358],{},"Durable spans are written before best-effort live events.",[1063,3360,3361],{},"Product-specific CRM\u002Fworkflow design remains outside this platform set.",[1063,3363,3364,3365,3367],{},"One ",[830,3366,2284],{}," still reaches both readers: the trigger matcher, and any Run waiting on it.",[1063,3369,3370,3371,3374],{},"A waiting Run is never failed on its heartbeat. The wait sweep is the one writer that ends one, and only past ",[830,3372,3373],{},"waiting_expires_at"," plus the grace window.",[1063,3376,3377],{},"Every model call is metered, including the Front Door turn that precedes a Run.",[1063,3379,3380,3383,3384,3386],{},[830,3381,3382],{},"AccrualChecker"," reads ",[830,3385,2061],{}," and returns a decision. It never reads the rollup and never raises.",[1063,3388,3389,1033,3392,3395,3396,837],{},[830,3390,3391],{},"mark_waiting()",[830,3393,3394],{},"resume()"," stay a pair, so a Run never executes while it reads ",[830,3397,3398],{},"waiting",[1063,3400,3401],{},"A suspended Inngest run holds no concurrency slot. A workflow tree depends on it.",[1063,3403,3404,3406,3407,3410,3411,837],{},[830,3405,1704],{}," writes ",[830,3408,3409],{},"heartbeat_at",", so the reaper has a safe ",[830,3412,3413],{},"stale_after",[1063,3415,3416,3417,837],{},"Every write and send Tool declares ",[830,3418,3419],{},"repeatable",[1063,3421,3422,3423,3426,3427,837],{},"No type outside the context package is named ",[830,3424,3425],{},"Context",", and no bare type is named ",[830,3428,2280],{},[1063,3430,3431],{},"A pending approval is cancelled by an erasure request, never redacted in place.",[1063,3433,3434],{},"The principal narrows at a checkpoint and never widens.",[1063,3436,3437,3438,3440,3441,3443,3444,3446,3447,3449],{},"New platform code imports nothing from the legacy agent stack, every new module lives under ",[830,3439,2683],{},", which is the path the import contract binds, and every new platform table is created in the ",[830,3442,2414],{}," schema, never in ",[830,3445,2426],{},". Product state keeps the house pattern in ",[830,3448,2426],{},", per the exception in coexistence rule 1.",[1063,3451,3452],{},"The web process serves no Inngest function. Every Inngest function runs on the Connect worker.",[1063,3454,3455],{},"A function's Inngest id embeds its app id. No app is renamed, and no function moves between apps, once it has run.",[1063,3457,3458,3459,3461],{},"A Run start is guarded by a unique index on ",[830,3460,1718],{},", so the insert is the claim and no start path needs a transaction.",[1063,3463,3464],{},"Every Run lifecycle write is conditional on the legal from-states, so a terminal Run stays terminal.",[1063,3466,3467,3468,3470],{},"Every bounded payload passes the one ",[830,3469,1796],{}," helper. No layer writes its own truncation.",[1063,3472,3473],{},"No surface returns an unbounded list, and no detail response embeds one. A related set is a page of a list route.",[1063,3475,3476],{},"Every refusal a domain component returns maps to exactly one HTTP status, in one table on the page that owns the route.",[1063,3478,3479,3480,3482],{},"The Run snapshot and the Run ",[830,3481,1737],{}," are size checked and never truncated. Both refuse the start rather than drop an item, because a drop there changes what the Run does and no field records it.",[1063,3484,3485,3486,3488],{},"The principal grant lives in ",[830,3487,2355],{},", and no other page lists it inside the snapshot.",[1063,3490,2365,3491,3493,3494,3496],{},[830,3492,2223],{}," definition refuses a new Run tree and allows a child of a running tree, in the trigger and in ",[830,3495,1050],{}," alike.",[1063,3498,3499,3500,3503,3504,1023,3507,1033,3510,3513,3514,3517,3518,3520,3521,837],{},"Every definition write that carries authored configuration -- the draft save and the publish -- is conditional on ",[830,3501,3502],{},"expected_updated_at",", so a stale writer reloads rather than overwriting. ",[830,3505,3506],{},"disable",[830,3508,3509],{},"enable",[830,3511,3512],{},"delete_draft"," carry no token: the first is an emergency switch that must not answer ",[830,3515,3516],{},"stale",", and none of the three overwrites authored work. ",[830,3519,3502],{}," travels as an opaque string, because a millisecond-precision client that re-formats it makes every write answer ",[830,3522,3516],{},[1063,3524,3525,3526,3529],{},"Agno is imported under ",[830,3527,3528],{},"runtime\u002Fagent\u002Fagno\u002F"," and nowhere else. The tool adapter counts.",[1063,3531,3532,3533,3535],{},"No exception raised by ",[830,3534,1234],{}," inside the Agno loop is left for Agno to swallow. The adapter classifies every one of them into the segment's stop signal.",[1063,3537,3538],{},"The segment stop signal lives on the segment. No mutable run state sits on a shared runtime instance.",[1063,3540,3541,3542,3545],{},"Every segment carries the system block it should run with. ",[830,3543,3544],{},"context = None"," means reuse the stored one, never trust the framework to keep it.",[1063,3547,3548,3549,3551],{},"A write or send call is decided and executed outside the Agno loop. Agno pauses, ",[830,3550,1234],{}," runs the call, and the result fills that call's own empty slot.",[1063,3553,3554,3555,3557],{},"No query filters on a list of identifiers that grows with a Run tree. Denormalize ",[830,3556,2052],{}," and filter on it, because PostgREST sends the filter in the URL and Kong refuses a request line over 8 KB.",[1063,3559,3560],{},"One pricer answers the cost of a model call, and the count it is given excludes the cache reads. The vendor reports tokens and no price, and a provider that folds cache reads into its input count prices them two times.",[1063,3562,3563],{},"The agent loop is left at the tool adapter or at the drain loop. No code abandons the framework event iterator, because an abandoned iterator leaves an open span and an unwritten session.",[1063,3565,3566],{},"A session write names the segment that produced it and never goes backwards, and the database refuses one that does. Two workers can hold one segment, and an invariant that lives only in the application is one forgotten predicate away from putting an older message history back with nothing reporting the loss.",[1063,3568,3569],{},"No exception the agent framework raises reaches the caller. Every model fault is kept beside the segment stop and classified after the stream ends, on the status the vendor sent and never on the name of the exception class: the rate limit type subclasses the refusal type, so reading the names inverts the rule and one 429 ends a run a replay would have saved.",[1063,3571,3572],{},"An asynchronous provider job stores its state transition before the platform emits the completion event. The row is the durable truth and the event is a wake-up signal, so a lost event costs a timeout and never a lost result.",[1063,3574,3575,3576,3579],{},"A provider cost settles one time, guarded by a conditional write on a null ",[830,3577,3578],{},"usage_id",". It settles off the Run frame, so a Run that was cancelled or timed out still carries the money it spent.",[859,3581,3583],{"id":3582},"product-designs","Product designs",[810,3585,3586],{},"These apply the platform to AgencyCore product features. They do not redefine runtime, tools, policy, context, triggers, idempotency or observability.",[864,3588,3589,3597],{},[867,3590,3591],{},[870,3592,3593,3595],{},[873,3594,1270],{},[873,3596,1273],{},[880,3598,3599,3608,3617,3626,3635,3647],{},[870,3600,3601,3605],{},[885,3602,3603],{},[814,3604,6],{"href":297},[885,3606,3607],{},"Cross-product lead-generation loop, the three product-state layers, scoring, review boundary and shared CRM context",[870,3609,3610,3614],{},[885,3611,3612],{},[814,3613,352],{"href":351},[885,3615,3616],{},"One bounded discovery workflow: companies, signals, relevant people, one Organization Prospect result, saved search, scheduled monitoring and CRM promotion",[870,3618,3619,3623],{},[885,3620,3621],{},[814,3622,333],{"href":332},[885,3624,3625],{},"Envoy durable outreach: personalized drafting, send, approval, waits, replies, follow-ups and Nylas boundary",[870,3627,3628,3632],{},[885,3629,3630],{},[814,3631,339],{"href":338},[885,3633,3634],{},"The default answer path: answer from supplied context, cite what it used, ask when context is insufficient, and delegate real work",[870,3636,3637,3641],{},[885,3638,3639],{},[814,3640,307],{"href":306},[885,3642,3643,3644],{},"Conversational authoring: one Definition Builder Agent turns chat into a validated Agent\u002FWorkflow draft and publishes it through ",[830,3645,3646],{},"DefinitionService",[870,3648,3649,3653],{},[885,3650,3651],{},[814,3652,345],{"href":344},[885,3654,3655],{},"The product view over the shared approval row: review types, page structure, filters, empty and stale states",[810,3657,3658],{},"Two earlier product pages are retired:",[1562,3660,3661,3667],{},[1063,3662,3663,3666],{},[822,3664,3665],{},"Signals Search replaces Sonar and Headhunter."," Company discovery and people discovery are one bounded workflow producing one Organization Prospect, not two chained product Runs.",[1063,3668,3669,3672],{},[822,3670,3671],{},"The email sequence workflow replaces Icebreaker."," Personalized drafting is a stage of durable outreach execution, not a separate product.",[810,3674,3675,3676,3678],{},"Product apps stay standalone user-facing products. Product state belongs to the product domain; generic execution state belongs to ",[830,3677,1050],{}," and Runs. No product feature gets its own scheduler, queue, Run table, policy engine, memory store or integration layer.",[3680,3681,3682],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}",{"title":845,"searchDepth":32,"depth":233,"links":3684},[3685,3686,3687,3688,3689,3690,3691,3696,3697,3698,3699,3700,3704,3705,3706,3707],{"id":861,"depth":32,"text":862},{"id":1015,"depth":32,"text":1016},{"id":1057,"depth":32,"text":1058},{"id":1155,"depth":32,"text":1156},{"id":1244,"depth":32,"text":1245},{"id":1257,"depth":32,"text":1258},{"id":1486,"depth":32,"text":1487,"children":3692},[3693,3694,3695],{"id":1497,"depth":233,"text":1500},{"id":1599,"depth":233,"text":1600},{"id":2080,"depth":233,"text":2083},{"id":2162,"depth":32,"text":2163},{"id":2300,"depth":32,"text":2301},{"id":2316,"depth":32,"text":2317},{"id":2389,"depth":32,"text":2390},{"id":2739,"depth":32,"text":2740,"children":3701},[3702,3703],{"id":2823,"depth":233,"text":2824},{"id":2926,"depth":233,"text":2927},{"id":612,"depth":32,"text":2578},{"id":3224,"depth":32,"text":3225},{"id":3318,"depth":32,"text":3319},{"id":3582,"depth":32,"text":3583},"md",{},[3711,3712,3713,3714,3715,3716,3717,3718,3719,3720,3721,3722,3723,3724,3725,3726,3727,3728,3729,3730],"engineering\u002Fsystem-design\u002Fagentic-platform","engineering\u002Fsystem-design\u002Fagentic-platform\u002Finterfaces\u002Fagent-access","engineering\u002Fsystem-design\u002Fagentic-platform\u002Finterfaces\u002Fsurfaces","engineering\u002Fsystem-design\u002Fagentic-platform\u002Finterfaces\u002Fchannel-gateway","engineering\u002Fsystem-design\u002Fagentic-platform\u002Finterfaces\u002Ffront-door","engineering\u002Fsystem-design\u002Fagentic-platform\u002Finterfaces\u002Ftriggers","engineering\u002Fsystem-design\u002Fagentic-platform\u002Fruntime","engineering\u002Fsystem-design\u002Fagentic-platform\u002Fruntime\u002Fdefinitions","engineering\u002Fsystem-design\u002Fagentic-platform\u002Fruntime\u002Fexecution","engineering\u002Fsystem-design\u002Fagentic-platform\u002Fcapabilities\u002Ftools-and-integrations","engineering\u002Fsystem-design\u002Fagentic-platform\u002Fcapabilities\u002Fstate-and-knowledge","engineering\u002Fsystem-design\u002Fagentic-platform\u002Fplanes\u002Fidempotency","engineering\u002Fsystem-design\u002Fagentic-platform\u002Fplanes\u002Fpolicy-and-governance","engineering\u002Fsystem-design\u002Fagentic-platform\u002Fplanes\u002Fobservability-and-operations","engineering\u002Fsystem-design\u002Fagentic-platform\u002Fproducts\u002Fagentic-crm","engineering\u002Fsystem-design\u002Fagentic-platform\u002Fproducts\u002Fsignals-search","engineering\u002Fsystem-design\u002Fagentic-platform\u002Fproducts\u002Femail-sequence","engineering\u002Fsystem-design\u002Fagentic-platform\u002Fproducts\u002Fgeneral-chat","engineering\u002Fsystem-design\u002Fagentic-platform\u002Fproducts\u002Fbuilder-chat","engineering\u002Fsystem-design\u002Fagentic-platform\u002Fproducts\u002Fhuman-review",{"title":204,"description":205},"engineering\u002Fsystem-design\u002Fagentic-platform\u002Fcontract",[12,14,197,142,194,207,149,208,198,209],"6SxOpdSPx-_TZfDDLLBgYoPxL8QeuRPv9RN5wnDa8_s",1788650190116]