Skip to content

automations: feat: add shared automations protocol - #393

Open
Ulugbek Abdullaev (ulugbekna) wants to merge 10 commits into
microsoft:mainfrom
ulugbekna:ulugbekna/shared-automations
Open

automations: feat: add shared automations protocol#393
Ulugbek Abdullaev (ulugbekna) wants to merge 10 commits into
microsoft:mainfrom
ulugbekna:ulugbekna/shared-automations

Conversation

@ulugbekna

@ulugbekna Ulugbek Abdullaev (ulugbekna) commented Aug 12, 2026

Copy link
Copy Markdown

Summary

Add shared, host-owned Automations to Agent Host Protocol.

The protocol represents:

  • durable automation definitions and optimistic revisions;
  • manual, schedule, and host-defined event triggers;
  • task-level runs with lifecycle, blockers, artifacts, and cancellation;
  • one or more linked ordinary AHP sessions;
  • durable automation/run provenance on created sessions;
  • host capabilities for execution lifetime, creation, schedules, cancellation,
    preview, and retained history;
  • idempotent, cutover-safe imports from legacy schedulers.

Multiple clients connected to one authority can share one catalogue, scheduler,
run claim, and history instead of independently scheduling duplicate sessions.

Resource model

ahp-automation:

Owns the reusable definition:

  • title and initial user message;
  • provider, model, custom agent, working directories, and session config;
  • enabled state and trigger collection;
  • revision and next occurrence;
  • retained run summaries and permitted operations.

ahp-automation-run:

Owns one invocation:

  • manual or trigger provenance;
  • pending, running, blocked, completed, failed, or cancelled lifecycle;
  • blocker summary;
  • linked sessions and primary session;
  • run-scoped artifacts and permitted operations.

Ordinary session/chat channels remain authoritative for transcripts, tools,
confirmations, and changes.

Triggers and execution

  • Schedule triggers use one portable five-field cron expression plus an IANA
    time zone.
  • The grammar covers numeric/named fields, wildcards, ranges, lists, steps, and
    Unix day-of-month/day-of-week matching.
  • Event triggers use authority-defined types, actions, and schema-defined
    configuration discovered through listAutomationTriggerDefinitions.
  • execution.lifetime distinguishes interactive hostLifetime scheduling from
    independently managed authorities.
  • runAutomation.requestId is a durable idempotency key.

Cutover-safe imports

createAutomation.import carries a stable source, batch, and item identity.
It may also carry each schedule trigger's next unevaluated source occurrence.

  • Imported definitions must be created disabled.
  • The host persists supplied occurrences while the definition is disabled.
  • After the client removes the legacy scheduler-visible copy and enables the
    host definition, overdue work follows the trigger's misfire policy.
  • A host must durably claim a due occurrence with its run record before external
    execution, preventing restart from dispatching the same catch-up twice.

This supports a migration with no interval where both old and new schedulers can
run the same definition.

Commands and synchronization

Adds:

  • listAutomations;
  • listAutomationTriggerDefinitions;
  • createAutomation;
  • updateAutomation;
  • disposeAutomation;
  • runAutomation;
  • fetchAutomationRuns;
  • previewAutomationSchedule;
  • root catalogue notifications;
  • definition/run-summary reducer actions;
  • run lifecycle/session/artifact reducer actions;
  • client-dispatchable run cancellation.

Presence capabilities use optional objects rather than booleans so they can gain
feature-specific details without changing capability detection.

Generated surfaces

The contract is propagated through JSON Schema, reference documentation,
TypeScript, Rust, Go, Swift, Kotlin, reducer fixtures, and round-trip fixtures.
The guide documents authority, cron semantics, imports, revisions, lifecycle,
cancellation, retention, reconciliation, and security.

Deliberate boundaries

  • Sharing is within one authority; AHP does not replicate independent hosts.
  • Event types remain authority-defined.
  • Run-history deletion is not part of this revision.
  • Local and managed/cloud execution can be represented by separate authorities.
  • Session-list promotion is not modeled here yet; immutable automation
    provenance must not be cleared to change client presentation.

Main merge

Merged current AHP main through d6bf47d2, preserving its scoped
customization-enablement model. Additive generated-client conflicts were
resolved by updating the Rust generator and regenerating every client/schema.

Validation

  • npm run generate
  • npm run test
  • cargo test --workspace under clients/rust
  • npm run docs:build
  • 100% reducer branch coverage
  • change-fragment and release-metadata verification

Companion implementation

Companion VS Code draft PR:
microsoft/vscode#330463

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 935e37c8-2b68-40b1-9273-f195cb3af9a0
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 935e37c8-2b68-40b1-9273-f195cb3af9a0
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 935e37c8-2b68-40b1-9273-f195cb3af9a0
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 1131c2f6-bcd0-4012-9265-fdb2685179e7
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 1131c2f6-bcd0-4012-9265-fdb2685179e7
isClientDispatchable did not accept automation or automation-run actions,
so servers could not use it to reject server-only actions arriving on the
new automation channels.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 1131c2f6-bcd0-4012-9265-fdb2685179e7
Comment thread types/channels-automation/state.ts Outdated
Comment thread types/channels-automation/state.ts Outdated
Comment thread docs/guide/automations.md Outdated
Comment thread types/channels-automation/state.ts
Collapse recurring schedules to the specified five-field AHP cron format, document the automation and run protocol surfaces, expand the guide, and regenerate every client and schema.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 1131c2f6-bcd0-4012-9265-fdb2685179e7
@ulugbekna
Ulugbek Abdullaev (ulugbekna) marked this pull request as ready for review August 12, 2026 19:50
Comment thread types/channels-automation/state.ts
Comment thread types/common/messages.ts
Comment thread types/channels-automation/reducer.ts
Comment thread clients/typescript/src/client/hosts/runtime.ts
Comment thread clients/typescript/test/client.test.ts
Comment thread scripts/generate-json-schema.test.ts
Comment thread types/channels-automation-run/state.ts
Comment thread docs/guide/automations.md
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 1131c2f6-bcd0-4012-9265-fdb2685179e7
Require imported definitions to remain disabled through cutover and let clients supply the source scheduler's next unevaluated occurrence. Document durable occurrence claiming so catch-up runs cannot be duplicated after restart.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 1131c2f6-bcd0-4012-9265-fdb2685179e7
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 1131c2f6-bcd0-4012-9265-fdb2685179e7

# Conflicts:
#	clients/go/ahptypes/state.generated.go
#	clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/State.generated.kt
#	clients/rust/crates/ahp-types/src/actions.rs
#	clients/rust/crates/ahp-types/src/state.rs
#	clients/rust/crates/ahp/src/reducers.rs
#	clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/State.generated.swift
#	scripts/generate-rust.ts
*
* @category Automation State
*/
export const enum AutomationOperation {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we expect these to be the only kinds of actions for automations? If yes, are they actually going to vary by automation or should then just be capabilities at the e.g. host level?

We have ChangesetOperation already which is a richer/more flexible type. When read "AutomationOperation" I initially assume that should be following the same pattern.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're at early stage of automations, so a bit hard to say if we expect other actions in future.

are they actually going to vary by automation or should then just be capabilities at the e.g. host level?

If we in future support automations to come for plugins, I would expect those would need to miss the "update" operation? (or any time when we would like an automation to be un-updatable/un-deletable, eg admin policy-driven automations)

Comment thread types/channels-automation/state.ts
* Values described by {@link AutomationTriggerDefinition.configSchema}.
* Clients MUST preserve unknown entries when editing other fields.
*/
config?: Record<string, unknown>;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would we want additional information from the AutomationTriggerDefinition/AutomationTriggerEventDefinition to aid in display here? Since looking them up again required a ListAutomationTriggerDefinitionsParams method call and potentially some enumeration under the hood...

workingDirectories?: URI[];
/** Opaque host-defined runtime metadata. */
_meta?: Record<string, unknown>;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unclear on how this is used. Automations already have their own session.workingDirectories, how is this different?

Comment on lines +324 to +325
/** Monotonic definition revision used for optimistic concurrency. */
revision: number;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this does not appear to actually be used

Comment on lines +276 to +283
export interface PreviewAutomationScheduleParams extends BaseParams {
/** Schedule preview is requested from the root channel. */
channel: 'ahp-root://';
/** Portable AHP cron schedule to evaluate. */
schedule: AutomationSchedule;
/** Requested maximum number of future occurrences; the host MAY cap it. */
count?: number;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unconvinced we need a whole protocol method for this. I would not be opposed to including a test case for cron scheduling in client libraries in this repo (like action tests, we should have a JSON assertion file and then have each language test against that fixture for consistency)

*
* @category Automation Run State
*/
export type AutomationRunCause =

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have the notion of origin's already for message and chat provenance, I suggest we use the same terminology here

Suggested change
export type AutomationRunCause =
export type AutomationRunOrigin =

*
* @category Automation Run State
*/
export const enum AutomationRunOperation {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same Q on operations here -- is this a capability or open ended operation

* @category Automation Run State
*/
export interface AutomationRunArtifact extends ContentRef {
/** Stable artifact id within this run, used by artifact actions. */

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. I don't see any notion of artifact actions in this PR
  2. These should be unique already by ContentRef.uri, no need for another ID

Comment on lines +217 to +223
export type AutomationRunLifecycle =
| AutomationPendingRunLifecycle
| AutomationRunningRunLifecycle
| AutomationBlockedRunLifecycle
| AutomationCompletedRunLifecycle
| AutomationFailedRunLifecycle
| AutomationCancelledRunLifecycle;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems in these we kind of reinvent/mirror the SessionInputRequest / SessionStatus but use slightly different terminology/interfaces. Can we consilidate these?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants