KDCube
← Engineering
KDCube Engineering · Deep Dive

KDCube Application Integrations: Provide, Consume, and Guard Every Surface

An integration has a direction, identity, authentication owner, capability boundary, delivery contract, and product owner.

18 July 2026Engineering18 minExperienceBlueprint Deck
app integrationsprovider surfacesconsumer surfacesConnection HubKDCube MCP integrationnamed servicesTelegram webhook

An integration is not just an endpoint. It has a direction, an identity, an authentication owner, a capability boundary, a delivery contract, and a product owner. KDCube apps declare what they provide and what they consume so an API, MCP server, agent tool, named service, widget, event lane, or Telegram channel does not acquire authority merely because it is reachable.

AI app integrations often begin as a list of URLs and tokens. That works until one app has several agents, one user connects several accounts, an external automation needs bounded access, or the same domain operation must work locally, through API, and through MCP.

KDCube treats the app as the integration boundary. Provider surfaces describe what the app offers. Consumer surfaces describe what the app and each of its agents may reach. The descriptor carries policy and product intent; code carries the implementation. Connection Hub handles linked identities, connected accounts, and delegated clients without giving raw provider credentials to an agent.

This is the deep integration map. The first-app and package story remains in Build an AI App with KDCube.

KDCube uses app in builder-facing prose. Literal contracts still use bundle in bundle_id, bundles.yaml, /bundles/ routes, and SDK decorator names. They identify the same deployable unit.

00Implementation highlights

ConceptThe takeaway
Provider and consumer are separate declarationsRegistering a connection does not expose it to every agent, and implementing a surface does not authorize every caller.
Transport and authentication are separateA public route may still verify webhook proof or use managed MCP authorization; a reachable URL is not an authority decision.
MCP does not require named servicesAny app can expose ordinary FastMCP tools or consume any supported MCP server directly.
Named services add domain semanticsUse them when several apps, agents, or transports should share one typed realm grammar and owner.
Identity is selected per connectionA consumed call can act as the app, as a user under one agent's delegated grant, or through the user's connected external account.
Telegram is queued ingressThe public webhook verifies proof, resolves the linked identity, submits a conversation event, acknowledges early, and leaves turn execution to proc.

01Two directions, one app boundary

An app can provide capabilities, consume capabilities, or do both.

                       KDCube app

callers / proc  --->  AS PROVIDER
                      surfaces this app implements
                      API, MCP, UI, handlers, jobs, public content,
                      named-service realms

                      AS CONSUMER  --->  services / providers / other apps
                      connections this app may open
                      MCP, tools, named services, models, scene surfaces,
                      connected accounts

Provider/consumer describes capability ownership, not simply arrow direction on the wire. A @data_bus_handler receives data, but it is a provider declaration because the app offers that handler to proc. An agent turn enters through @on_reactive_event, while the agent then consumes tools and services from its own inventory.

The two descriptor families keep those decisions visible:

descriptorYAML
surfaces:  as_provider:    # What this app offers and the policy on each offered surface.   as_consumer:    # What this app and each of its agents may reach.

Code decorators say a surface exists. The descriptor says what that surface means in this deployment: enabled state, visibility, authentication owner, default-chat intent, connection details, per-agent inventory, or scene composition.

Provider and consumer integration planes A KDCube application boundary sits between provider surfaces it owns and consumer connections it may use. Every crossing has a policy gate. BLUEPRINT A · INTEGRATION DIRECTION One application boundary. Two explicit directions. Implementation declares a surface; deployment policy decides whether and how the line may cross. AS PROVIDER Surfaces this app owns APIREST MCP servertools UIview/widget Eventshandlers Jobscron/worker Public contentcatalog Named servicesrealms KDCUBE APPLICATION Trusted app code IMPLEMENTATION decorators · handlers · adapters DEPLOYMENT POLICY enabled · visibility · auth owner inventory · identity · grants AS CONSUMER Connections this app may use MCP servers Python tools Named-service realms Models Connected accounts Scene surfaces GATE GATE IMPLEMENTATION · POLICY · DIRECTION REMAIN SEPARATE
Blueprint Deck elevation. One app boundary in the center. Provider ports leave left: API, MCP, UI, events, jobs, public content, named services. Consumer sockets leave right: MCP servers, Python tools, named-service realms, models, connected accounts, scene surfaces. Each port has a small policy gate before the line crosses the app boundary. Caption: "Implementation, policy, and connection direction remain separate."

02What an app can provide

An app exposes only the surfaces it owns.

Provider surfaceCode declarationWho normally calls it
Reactive conversation turn@on_reactive_event on the entrypointchat ingress and proc's ordered conversation scheduler
Authenticated or public REST operation@api(route="operations") or @api(route="public")KDCube UI/internal caller, webhook, partner system
MCP server@mcp(...) returning a stateless FastMCP apphosted or external MCP clients
Widget or main view@ui_widget, @ui_mainKDCube scene/host/browser
Scheduled/background work@cron, @on_jobproc scheduler and job workers
Durable app-domain message handler@data_bus_handlerwidget, UI, app, or service through Data Bus
Discoverable public content@public_contentcrawler, catalog reader, public site
Named-service realmexplicit provider contributionagents, apps, widgets, tools through local/API/MCP/Data Bus adapters

The decorators are not a checklist. A backend API app does not need chat. An MCP provider does not need a named-service realm. A site does not need a scene. A named-service provider can offer no public URL at all when its callers are runtime-local.

Provider ownership must be explicit. A reusable base class that contains memory-capable code does not make every derived app a memory provider. The owner app contributes the provider to its registry; discovery publishes the complete current registry and withdraws providers no longer owned.

03Every inbound surface names its trust boundary

The proc router delivers all app surfaces, but authentication ownership varies.

SurfaceNormal trust ownerImportant limit
@api(route="operations")KDCube session/auth stack plus declared user/role checksapp still owns record-level product authorization
@api(route="public")app/SDK proof verifier or configured managed guard"public route" means no normal browser login gate, not "trust every caller"
Widget/main viewKDCube session and widget/runtime config handshakebrowser receives presentation/runtime config, not app secrets
Public contentintentionally anonymous published item stateinputs, catalogs, rate, and publish/retract lifecycle remain bounded
MCP with no auth modeintentionally publicsuitable only for genuinely public tools
MCP auth.mode: bundleapp-owned credential verifierapp must implement the proof and authorization policy
MCP auth.mode: managedproc plus Connection Hubdelegated bearer, resource, grants, selected tools, expiry, and revocation checked before app code

Transport is not policy. A route="public" MCP URL is often necessary for MCP discovery and OAuth challenge, while auth.mode: managed still rejects an unauthorized tool call before the FastMCP app runs.

Likewise, a Telegram webhook is a public API route because Telegram cannot present the user's browser session. It is still authenticated by the configured Telegram proof and linked-identity flow.

For managed MCP, the boundary journey is:

external request
  -> verify delegated bearer
  -> load server-side grant
  -> match concrete resource
  -> check requested tool and required grants
  -> check selected/consented operations
  -> project delegate actor + approving user into request context
  -> invoke app MCP tool
  -> app performs record-level authorization

The bearer is a handle. The server-side grant remains the authority.

Inbound application surfaces and their trust gates Three inbound rows show authenticated operations, a public webhook with provider proof, and managed public MCP with OAuth bearer validation before trusted app code. BLUEPRINT B · INBOUND TRUST Reachability is not authorization. Each surface states who verifies the caller before trusted application code receives the request. OPERATIONS API Authenticated REST session + role policy KDCUBE AUTH GATE session · user · roles app still owns record-level checks PUBLIC WEBHOOK Provider callback no browser login gate PROVIDER PROOF signature · state · secret public route does not mean trust all PUBLIC MCP External tool client streamable transport MANAGED MCP GUARD OAuth bearer · resource grants tool-level authorization TRUSTED APP CODE declared handler async business logic PRODUCT AUTHORIZATION record · object · domain policy owned mutation / result TRANSPORT EXPOSURE ≠ AUTHORITY
Three Blueprint Deck gate sections: operations API behind KDCube session gate; public webhook behind app proof gate; public-route MCP behind Connection Hub managed gate. All three reach the same trusted app code box. A note reads "Route family chooses delivery. Authentication mode chooses authority."

04Consuming MCP has a registry and an inventory

An app that consumes MCP makes two declarations:

surfaces.as_consumer.mcp.services
  where the servers are and how a client may authenticate

surfaces.as_consumer.agents.<agent_id>.tools
  which server and tools this agent may see and call

Those declarations answer different questions:

connection registry: "where is it and how can the app reach it?"
agent inventory:      "may this agent know and call it, as whom?"

One MCP server can serve several agents with different allow-lists. Registering the server does not expose it to any agent automatically. The effective tool catalog is the administrator's ceiling intersected with the user's conversation selection.

A consumed tool call can run under three useful identity paths:

ModeConfigurationCall identity
App credentialbearer/API-key/header secret referencethe app itself
Delegated user per agentdelegated: true, resource id, requested KDCube claimssigned-in user under this specific hosted agent's resource-scoped grant
Connected accountprovider claims checked by the tool/provider adapteruser's external Gmail, Slack, or other account

The first two bind the service/client call. A connected account is a tool-level provider requirement behind that call; it does not replace the MCP transport's own authentication or managed guard.

Static credentials belong in app secrets, never in the MCP URL, tool arguments, model prompt, or generated code.

For delegated mode, the hosted agent is its own delegated client:

kdcube-agent:<app-id>:<agent-id>

Each delegated connection asks for claims under its configured KDCube resource. Consent stores that decision in resource_grants; repeated consent for the same deterministic agent and resource can merge further claims into that grant. Other resources and sibling agents gain nothing implicitly. The runtime reuses the bound token for subsequent turns. After revocation, the next bearer resolution no longer binds the connection and a direct guarded call fails.

Consent is demand-driven. KDCube does not sweep every configured tool at the start of a turn. When the agent first attempts a tool whose delegated grant is missing, the runtime can emit an actionable consent demand with the Connection Hub approval link instead of pretending the tool does not exist. After the user approves, a later attempt resolves the bound grant and token.

Three consumption identities Three lanes map configuration to call identity. App credential — a bearer, API key, or header secret reference — calls as the app itself, one identity for every call. Delegated per agent — delegated true with a resource id and requested claims — calls as the signed-in user under this one agent's resource-scoped grant. Connected account — provider claims checked by the adapter — calls as the user's external Gmail, Slack, or other linked account. A warm plate notes identity is selected per connection, in the descriptor, never in code. BLUEPRINT E · CONSUMPTION IDENTITY Same server, three different callers. The registry makes a server available; each connection declares whose authority the call carries. APP CREDENTIAL bearer / API-key / header secret reference the app itself one identity for every call this app makes DELEGATED PER AGENT delegated: true · resource id · requested claims the signed-in user under this one agent’s resource-scoped grant CONNECTED ACCOUNT provider claims checked by the adapter the user’s external account Gmail, Slack, or another provider the user linked IDENTITY IS SELECTED per connection, in the descriptor — never in code REGISTRY MAKES A SERVER AVAILABLE · THE CONNECTION DECLARES THE IDENTITY
Same server, three different callers — the connection declares the identity.

05Named services are an optional semantic layer

Ordinary MCP is enough when the product has a small, transport-specific tool surface:

search_reports
get_report
create_invoice

A named service is useful when the platform should understand a reusable realm across apps, agents, widgets, and transports:

provider.about
provider.capabilities
object.search
object.get / object.action
relation.*
event.resolve
block.produce / block.render

The owner app defines refs, object kinds, search scopes, operations, presentation, guards, and connected-account claims. Its registry publishes an authoritative snapshot into tenant/project discovery. A consumer resolves the provider locally when loaded in the same runtime or through a declared transport when it lives elsewhere.

one provider implementation
  -> runtime-local client
  -> REST adapter
  -> MCP adapter
  -> Data Bus relay

The adapters hydrate caller context and protocol envelopes; they do not reimplement the domain.

Named services therefore solve "one domain grammar, several consumers." They are not a prerequisite for exposing an app through MCP, and they should not be added merely to make a product-specific tool sound generic.

Provider ownership is an explicit app decision:

SDK examplePYTHON
class FreightEntrypoint(BaseEntrypointWithEconomics):    def _named_service_providers(self) -> list:        providers = list(super()._named_service_providers())        providers.append(self._freight_provider())        return providers

The complete registry published by that app is authoritative for its current contribution. Implementing reusable provider code in a base class does not silently make every derived app an owner.

A consuming app grants a specific agent only the operations it needs:

descriptorYAML
surfaces:  as_consumer:    agents:      main:        tools:          - kind: named_service            alias: named_services            namespaces:              freight:                allowed:                  - provider.about                  - object.search                  - object.get                  - object.action

Tenant/project discovery finds the owner contribution. The consumer config sets its allowed operation ceiling; the provider still parses refs, enforces actions, and owns returned object semantics. Other consumers, such as a widget resolver or background job, call the same provider contract under their own current AuthContext.

06Connection Hub governs both delegation directions

Two integration directions are easy to confuse:

Connection Hub viewMeaning
Delegated to KDCubethe user connects an external account so trusted KDCube code may use that provider on the user's behalf
Delegated by KDCubethe user grants a hosted agent, external MCP client, or automation bounded access to KDCube resources

The first direction stores provider-account metadata separately from raw provider credentials. Trusted provider adapters resolve the credential server-side only after the required account claims pass.

This first direction also has an operator prerequisite: Connection Hub must have a provider adapter and connector app configured, including its allowed_claims ceiling and secret client credential. A tool can request only claims inside that ceiling; connecting an account cannot invent provider permissions the connector app was never configured to request.

The second direction creates a server-side grant for a concrete client. Its authority includes resource_grants (resource to grants/claims), optional selected operations/tools, identity scope, expiry, and revocation state. The client receives a bounded bearer handle, not the user's browser session.

For a hosted agent to use the user's Slack account through the KDCube named-services MCP bridge, both decisions must hold:

per-agent Delegated by KDCube grant
  allows this agent into the named-services MCP resource
  with KDCube resource grants:
  named_services:use + the Slack tool's declared claims
          AND
user's Delegated to KDCube Slack connection
  has the provider account and its approved provider claims
          |
          v
provider adapter resolves token server-side and executes

Revoking either side causes subsequent calls to stop. The agent never receives the Slack token.

Consent can expose the nested KDCube claims required behind a selected MCP tool. The user chooses which claims to place under that KDCube resource; the runtime enforces the accepted resource/tool/grant set at the managed boundary. Separately, the provider adapter checks the connected account and its provider-approved claims at the actual Slack call. The vocabulary may contain the same slack:* names, but the two records are independent and neither one implies the other.

Two independent delegation consents A connected provider account and a delegated external client are separate user decisions. Both must be satisfied before an external client can invoke a tool that uses the provider account. BLUEPRINT C · TWO DELEGATION EDGES The user makes two independent decisions. One allows KDCube to use an external account; the other allows an external client to use KDCube. DELEGATED TO KDCUBE Connected provider account Gmail · Slack · custom OAuth/OIDC service provider claims approved by user DELEGATED BY KDCUBE Bounded automation client Claude · script · service · operator automation resource → grants approved by user ACCOUNT LOCK CLIENT LOCK TOOL INVOCATION external client principal resource grants satisfied provider adapter resolves handle tool claims satisfied for selected account raw credential stays on trusted side BOUNDED RESULT ONE CONSENT NEVER IMPLIES THE OTHER
Two independent blueprint keys enter one locked operation. Top key: "Delegated by KDCube: this agent -> named-services resource + KDCube resource grants". Bottom key: "Delegated to KDCube: this user -> connected Slack account + provider claims". Behind the lock, the provider adapter holds the raw Slack credential. The agent side receives only the bounded result.

07External clients and hosted agents use the same principal class

Connection Hub's Delegated by KDCube registry can contain:

  • an external OAuth/MCP client such as Claude Code;
  • a manually created automation token;
  • a hosted agent acting for the current user.

All are delegated clients, but they have distinct client ids and grants.

An external MCP client follows discovery, authorization, consent, and token exchange. A manual automation receives a token once from the Connection Hub UI. A hosted agent raises an in-product consent demand and later resolves its per-agent grant through the connections SDK.

They converge at enforcement:

presented bearer
  -> bound server-side grant
  -> resource_grants + selected operations + expiry + revocation
  -> projected actor/grantor authority
  -> protected app surface

No path receives the user's unrestricted browser session. This is what lets an operator revoke one agent without revoking its sibling, or narrow one external automation without changing the app's own credential.

08Telegram is a public ingress adapter, not an inline agent runtime

A Telegram-capable app exposes a public webhook surface, but the webhook should remain thin:

Telegram Bot API
  -> POST app public telegram_webhook
  -> verify configured webhook proof
  -> claim update_id for idempotency
  -> hydrate Telegram files
  -> resolve Telegram actor and Connection Hub identity edge
  -> submit normal conversation external_events[]
  -> acknowledge Telegram early

proc later claims queued conversation turn
  -> runs the app's reactive surface
  -> streams permitted activity
  -> renders final result/files from the turn record
  -> sends through Telegram Bot API

The Telegram actor does not become a platform user because its numeric id appears in a payload. Connection Hub verifies the channel identity and resolves the explicit link/delegation edge to a platform subject. An unlinked actor receives the connection flow.

The webhook does not keep an HTTP request open while an agent reasons and does not start a private answer subscriber. It reuses the same conversation scheduler and turn result contract as the browser channel.

Telegram queued ingress integration Telegram sends a webhook to a public KDCube route. The route verifies proof, resolves the linked user and conversation, durably submits a conversation event, acknowledges early, and proc runs the turn later. BLUEPRINT D · TELEGRAM INGRESS Verify, admit, acknowledge. Execute later. The webhook is a public adapter into the conversation lane, not an inline agent runtime. Telegram webhook POST 01 Verify proof secret / signature reject invalid input 02 Resolve link platform user conversation + agent 03 Durable submit conversation event ordered lane 04 Proc turn agent executes outside webhook 05 Deliver reply / file later EARLY ACKNOWLEDGEMENT after durable admission, before model work THE DELIVERY CONTRACT Telegram retries belong at webhook admission; agent retries belong in the durable conversation workflow.
Blueprint sequence from Telegram to public webhook, proof/idempotency/identity edge, chat ingress queue, proc turn, and Telegram delivery. Put a bold return arrow from webhook to Telegram before proc execution labeled "acknowledge early".

09Four complete integration journeys

Four complete integration journeys Four panels. Journey one, a widget mutates app state: authenticated widget to Data Bus message with subject, object_ref, idempotency key, proc-owned handler dispatch, domain authorization and durable write, transient success or conflict reply — the app database is authority, the stream is delivery. Journey two, an external agent calls app MCP: Connection Hub OAuth and consent, a bounded delegated bearer, the managed MCP guard into the FastMCP tool, then product record-level authorization — the guard runs before any app code. Journey three, a hosted agent calls an external provider: the agent's per-resource grant plus the user's connected provider account, a named-service or provider adapter, server-side credential resolution, a bounded result — the raw credential never reaches the agent. Journey four, one app consumes another: named-service discovery by namespace, a local provider call when available, otherwise the configured adapter, with provider-owned object, ref, and guard semantics — the provider app remains the domain owner. BLUEPRINT F · FOUR COMPLETE JOURNEYS Four edges, one discipline. Every journey ends at an owner: a database, a guard, a provider — never at an unowned surface. J1 · WIDGET MUTATES APP STATE authenticated widget → Data Bus message subject · object_ref · idempotency key proc-owned handler dispatch domain authorization · durable write transient success / conflict reply the app database is authority; the stream is delivery J2 · EXTERNAL AGENT → APP MCP external MCP client Connection Hub OAuth / consent bounded delegated bearer managed MCP guard → FastMCP tool product record-level authorization the guard runs before any app code J3 · HOSTED AGENT → EXTERNAL PROVIDER agent’s per-resource grant + user’s connected provider account named-service or provider adapter server-side credential resolution bounded result to the agent the raw credential never reaches the agent J4 · ONE APP CONSUMES ANOTHER consumer app named-service discovery by namespace local provider call when available otherwise the configured adapter provider-owned object / ref / guard semantics the provider app remains the domain owner THE PROVIDER REMAINS THE DOMAIN OWNER IN EVERY TRANSPORT
Four edges, one discipline — every journey ends at an owner.

The four journeys share one discipline. The app database remains the authority and the Data Bus stream is delivery; the managed guard runs before any app code; server-side credential resolution keeps raw provider secrets away from agents; and the provider app remains the domain owner in every transport.

10Choose the narrowest surface that preserves the contract

NeedStart with
Browser or internal request/responseauthenticated @api(route="operations")
Provider callback or webhook@api(route="public") plus explicit proof
Standard agent tool protocolordinary @mcp provider/consumer
Reusable object realm across apps and agentsnamed-service provider/client
Durable browser-to-app mutationData Bus handler
Ordered agent-visible inputconversation external event
Retryable deferred workbackground job
Scheduled work discoverycron producer plus job handler
Product UIwidget or main view, scene only when composition is needed
Crawlable public contentpublic-content provider
User's external accountConnection Hub connected-account path
External or hosted delegated clientConnection Hub Delegated by KDCube

The architecture stays small when each integration earns its surface. A single API need not become a named service. An MCP tool need not become chat. A Telegram adapter need not invent another scheduler. A local cross-app call need not traverse public ingress.

11Integration review

For every new edge, answer:

  1. Is the app providing or consuming this capability?
  2. Which code declaration implements it, and which descriptor path carries policy?
  3. Who authenticates the caller: KDCube, the app, Connection Hub, or an external provider?
  4. Which actor and user subject reach product storage?
  5. Is the call acting as the app, one hosted agent under user delegation, or a connected external account?
  6. Are credentials resolved server-side and excluded from prompts, generated code, URLs, and logs?
  7. Is the transport durable, transient, or request/response, and where does authoritative state live?
  8. Can the grant/account/edge be inspected and revoked independently?
  9. Does this domain really need named-service semantics, or is ordinary API/MCP the clearer surface?

Those questions turn an integration inventory into a governable system.

Read the contracts

Platform documentation:

Related public articles and recipes:

The Markdown file beside this page is the approved indexing source. Literal platform contracts retain names such as bundle_id, bundles.yaml, and SDK bundle decorators.

KDCube Engineering
18 · 07 · 2026