feat(teams): add operator cron delivery - #1504
Draft
NeoHsu wants to merge 18 commits into
Draft
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Important
Stacked draft: logical base
stack/teams-11-conversation-registryis PR #1503. GitHub requires an upstream PR base to exist inopenabdev/openab, so this draft temporarily targetsmainand may show preceding stack layers. Do not merge it until #1503 is merged and this branch is rebased onto currentmain; then review only its single incremental commit.What problem does this solve?
Allow an operator-authored baseline cron job to send a scheduled prompt and its
agent response into one exact active, non-expired PR 11 Teams conversation in
Unified or Standalone mode, with required delivery outcomes, Gateway-local
reference resolution, lifecycle reconciliation, no synthetic Teams thread, and
no persistent reference or
serviceUrlexposure to Core or ACP.Discord Discussion URL: https://discord.com/channels/1491295327620169908/1491365158868619404/1531339032527765655
Microsoft Teams roadmap discussion.
Review Contract
This is the proposed PR-body contract. It is not frozen until the owner or a
maintainer approves it and records the reviewed head plus an immutable contract
revision or hash.
Goal
Allow an operator-authored baseline cron job to send a scheduled prompt and its
agent response into one exact active, non-expired PR 11 Teams conversation in
Unified or Standalone mode, with required delivery outcomes, Gateway-local
reference resolution, lifecycle reconciliation, no synthetic Teams thread, and
no persistent reference or
serviceUrlexposure to Core or ACP.Non-goals
Agent-writable Teams usercron,
/remindor any user-created schedule, proactiveapp installation or conversation creation, Graph/RSC/delegated permissions,
registry CRUD or discovery, target aliases, catch-up after missed ticks,
automatic retry/backoff, durable outbound queues, new cron expression semantics,
new Teams thread creation, media/card cron payloads, restart-persistent activity
ownership, multi-Gateway coordination, cross-process locking, or sovereign-cloud
expansion are outside PR 12.
Accepted Residual Risks
Operator config contains the non-secret Teams tenant and conversation IDs plus
the scheduled prompt; filesystem and config access remain the operator's
responsibility. Scheduled activities are intentionally unprompted and PR 12 has
no user opt-out UI. A stale or removed installation can consume one failed
scheduled attempt, and the two-result disable threshold can allow one additional
explicit blocked/not-in-roster attempt before stopping future use. Clock shifts,
timezone changes, process downtime, and hello timing can skip a tick; there is
no catch-up. A Gateway disconnect after an accepted frame can leave delivery
Unknown, which suppresses retry but may omit that occurrence. Registryreconciliation can fail after an authoritative platform outcome, leaving prior
state until later evidence. The registry and topology retain PR 11's
single-writer/single-consumer and filesystem-confidentiality limits.
Acceptance Criteria
Default and non-Teams cron behavior remains backward compatible; only
operator-owned baseline config can target Teams and agent-writable usercron is
rejected before lookup; Teams config supplies a bounded tenant plus conversation
identity and forbids synthetic thread selection; Core emits an additive
persistent target only after the exact capability and supported topology are
available; old peers and registry-off deployments fail closed before wire, HTTP,
session, or ACP work; Gateway reconstructs and validates the complete
app/tenant/Bot-Framework-channel/conversation key, current tenant allowlist, and
active non-expired record without exposing its stored reference or
serviceUrl;one real-ID trigger delivery precedes ACP and all later writes preserve the same
target; Teams creates no scheduler thread; Standalone reconnects through one
stable proxy without a second consumer; Unified and Standalone are semantically
equivalent;
Delivered, exact consecutive blocked outcomes, otherRejectedoutcomes, and
Unknownupdate or preserve registry state exactly as declaredand never blind-retry; and target, prompt, response body, identifier, credential,
and endpoint logging guards hold.
Follow-ups
A separate user-reminder contract may bind the initiating user and trusted scope
and revalidate both at execution. Later work may add operator aliases and
registry audit/CRUD, opt-out controls, external-scheduler ingress, catch-up or a
durable outbox, media/card scheduled payloads, persistent bot-owned activity
reconciliation, encrypted/shared transactional storage, multi-replica
coordination, or sovereign-cloud profiles.
At a Glance
Prior Art & Industry Research
OpenClaw: its Microsoft Teams extension separates access checks, Bot Framework route context, and outbound operations. For this slice the relevant comparison is proactive Teams sends from previously trusted conversation context.
Hermes Agent: its Teams platform adapter keeps Teams-specific transport and message shaping behind a platform adapter. It does not provide OpenAB’s negotiated Core/Gateway outcome contract, so this PR keeps the useful adapter boundary but adds explicit fail-closed semantics.
Proposed Solution
[[cron.jobs]]to target one exact trusted Teams conversation.Why this approach?
Restricting authority to operator baseline jobs prevents agent-writable schedules from turning an old route into an ambient send capability.
Alternatives Considered
Allow usercron or
/remindto reuse persistent routes (rejected: missing user/scope revalidation) or retry Unknown sends (rejected: duplicates).Validation
cargo test -p openab-core cron::tests(79 passed)cargo test -p openab-gateway --features teams adapters::teams_registry::tests(14 passed)