agentsclimarketplace

Aevatar scheduler

Skill ChronoAIProject/NyxID/skills/aevatar-scheduler

Create and manage recurring Aevatar runs and route to the correct scheduling resource. Use for cron, recurring Team member workflows, scheduled skill agents, typed service invocations, pause/resume, run-now, reauthorization, deletion, or credential triage. Team member automation uses its dedicated route and Agent Key; generic schedules accept typed service invocation only. External raw actor/envelope schedules are retired and must fail closed.From its SKILL.md

Install
npx -y skills add ChronoAIProject/NyxID --skill aevatar-scheduler

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

SKILL.md

29.6 KB, as published. Nobody here has run it

Schedule an Aevatar service on a cron

Route to the right resource FIRST — three paths, not one

"Run it on a schedule" is three different resources with three different owners, credentials, and APIs. Pick before you call anything; using the wrong one is not a shortcut, it is the wrong resource.

The user wants to schedule…Resource ownerCanonical entryCredential
An already-bound Studio Team member workflowscope → team → memberaevatar_schedule_member_workflow, or REST /api/scopes/{scopeId}/teams/{teamId}/members/{memberId}/automationsDedicated Agent Key
An independent scheduled Ornn skill agent or a one-shot reminderScheduled agent / catalog actorsscheduled_agent_creator, then agent_builder — see aevatar-automationDedicated Agent Key
A typed service invocationGeneric platform schedule actorGeneric /api/schedules — the rest of this skillTyped source; may be a NyxID binding exchange

If the owner is a Team member, the canonical path is the member automation route — not generic /api/schedules. Generic /api/schedules is a platform-level resource for typed service invocations. It is supported, but it is not a fallback for Team member automation, and reaching for it because you already know its shape is the most common mistake here.

Never convert between identities by route position, prefix, equality, or a familiar-looking string: memberId, draft workflowId, publishedServiceId, UserService ID, catalog service ID, schedule ID, and Agent Key ID are seven distinct things.

Studio Team member automation (the canonical member path)

Use aevatar_schedule_member_workflow in-session, or the owner-scoped REST route. The owner is the exact scopeId + teamId + memberId tuple; teamId is a containment guard. The server reads the member summary and derives publishedServiceId — you never substitute a draft workflowId, a service ID, a binding ID, a route, a model, or a credential ID for it.

Preflight is read-only and provisions nothing. It builds a typed authorization plan from current facts: the exact member and containing Team, the bound workflow revision and prepared artifact, typed connector and NyxID capability refs, the owner LLM route/model and exact UserService ID where required, the owner-scoped NyxID authorization catalog, and policy/version/expiry/disclosure facts. Never invent grants, wildcards, node IDs, route or model choices, or caller binding evidence.

The two entry surfaces are intentionally not equivalent:

  • Existing member, in-session: prefer aevatar_schedule_member_workflow. If the member still points at an interactive revision, the tool can admit and publish an immutable durable revision, wait for that exact revision to become visible, pin it, rerun preflight, and create the automation. durable_revision_propagating means wait for projection visibility and retry the same operation; it is not permission to create another member. Durable admission publishes the new revision before the final schedule preflight. If that later preflight fails, the immutable revision may remain even though no automation was created; do not claim transaction rollback or delete/rebind it without an explicit lifecycle decision.
  • Raw REST: POST .../automations/preflight stays pure read. It can return non-retryable 409 TEAM_AUTOMATION_DURABLE_ADMISSION_REQUIRED or TEAM_AUTOMATION_DURABLE_REQUEST_GRANT_MISMATCH, but it never upgrades or rebinds a revision. Raw create consumes a confirmed plan; it has no hidden durable-upgrade flag.
  • No member yet: use aevatar_provision_workflow_schedule only when the user explicitly wants a new Team-owned workflow member and schedule. Do not use provisioning to clone an existing member or guess its Team.

Console flow

In Aevatar Console, open the target Scope and Team. Create a workflow member, edit the full YAML in Workflow Studio, apply it to the draft, save, publish, and wait for published/bind-ready state. Then open Automate / Recurring work, choose the published member, enter name, recurring prompt, five-field cron, IANA timezone, and enabled state, preview the next runs, and authorize the Dedicated Agent Key. Save is not publish, publish is not automation, and the accepted automation receipt is not active state. Never substitute workflowId or publishedServiceId for the member selected by the Console.

Fire-time prompt data

For a Chat workflow, the recurring prompt may be a fire-time JSON template. Supported placeholders are:

PlaceholderValue at the authoritative logical fire
{{@schedule.run_date}}Local yyyy-MM-dd in the configured schedule timezone
{{@schedule.run_year}}Local year
{{@schedule.run_month}}Local month without zero padding
{{@schedule.days_until_month_end}}Days after the local fire date through month end; today excluded
{{@schedule.fire_at_utc}}Logical fire instant in UTC
{{@schedule.timezone}}Normalized configured timezone

Example monthly input:

{"period_label":"{{@schedule.run_year}}年{{@schedule.run_month}}月","run_date":"{{@schedule.run_date}}","submit":false}

If any {{@schedule.*}} placeholder is present, the whole prompt must be valid JSON and every placeholder must occur inside a JSON string value, never a property name. Unknown variables, unmatched delimiters, invalid JSON, or an invalid timezone fail closed before schedule effects. Prompts without schedule placeholders remain byte-for-byte unchanged. Late/catch-up execution uses the original scheduled occurrence; run-now uses its manual fire instant. Therefore run-now can prove template rendering, but it cannot prove cron re-arming.

Do not freeze a monthly date or days_left into a recurring prompt. Do not use model knowledge or host wall-clock time as a business input when this contract can inject the logical fire date.

Authored write-call limitation

Admission scans the committed workflow definition, not only the branch selected by a sample prompt. submit:false therefore does not hide authored POST/PUT/PATCH/DELETE capability.nyxid_request call sites. On a deployment whose scheduled-operation authority port is unavailable, preflight fails closed with TEAM_AUTOMATION_NYXID_OPERATION_AUTHORITY_CONTRACT_UNAVAILABLE. Do not bypass it with a generic schedule, a webhook-effect permit, or an interactive confirmation. For a harmless schedule proof, publish a preview-only definition that physically contains no write call sites. Prefer a dedicated acceptance member/revision and short-lived automation so the production member is not rebound by a smoke test. If the user instead wants to replace the production member's revision, make that lifecycle change explicit first. A real unattended write requires supported durable operation authority, an exact admitted capability, downstream policy acceptance, and business idempotency.

Create uses credentialProvisioningKind = dedicated_scheduled_invocation_agent_key. The server revalidates the confirmed permission digest and policy version against current sources before any key-creation effect, then requests a fresh, targeted NyxID scope plan for the exact sorted UserService IDs. Key creation fixes allow_all_services = false and allow_all_nodes = false — only the targeted plan supplies allowed service IDs, node IDs, and the provider scope-plan digest.

Secret custody. The one-time raw key NyxID returns is written only to ISecretVault under purpose scheduled.invocation-agent-key. Durable state, events, read models, logs, tools, and public APIs expose only non-secret facts: a typed reference, Agent Key ID, expiry, authorization fact, and credential generation. Never ask the user to paste an Agent Key, accept one in schedule JSON, print one, store one in an Ornn package, or reconstruct one from an ID.

After a 202 — what it does and does not prove

202 Accepted (and tool status accepted / pending) means command admission only. It does not prove credential issuance completed, the Vault write completed, activation committed, the read model observed it, cron fired, or the workflow succeeded.

Reread the canonical owner-scoped automation and require a newer authoritative stateVersion. A ready automation normally shows:

  • authorizationStatus == active
  • credentialSourceKind == scheduled_invocation_agent_key
  • enabled == true (firing)
  • a credentialExpiresAtUtc later than the next intended fire (and long enough for the recurring operating window)
  • a positive credentialGeneration
  • revocationPending == false

Also require the exact owner tuple, target revision, cron, timezone, and unrendered prompt template to match what was authorized. Then verify at least one automatic fire with manual == false, empty current lastError / lastErrorCode, and a committed successful workflow run. Prefer two consecutive automatic fires for a short-lived smoke schedule so re-arming is proven. Delete or pause high-frequency smoke schedules after acceptance.

For a Team member, correlate the schedule to committed runs with GET /api/scopes/{scopeId}/members/{memberId}/runs?take=50&scheduleId={scheduleId} and then inspect the exact run. Require terminal success and, when testing a fire-time template, verify the committed run input contains rendered values and no residual {{@schedule. token. A Dispatched fire is not a completed workflow run.

failureCount is a lifetime counter, not current health. A successful fire clears current lastError while historical failures remain counted. Do not label a recovered automation as currently failing from failureCount > 0 alone.

Exact REST lifecycle

The current member-owned surface is nested under the full owner tuple:

POST   /api/scopes/{scopeId}/teams/{teamId}/members/{memberId}/automations/preflight
GET    /api/scopes/{scopeId}/teams/{teamId}/members/{memberId}/automations
POST   /api/scopes/{scopeId}/teams/{teamId}/members/{memberId}/automations
GET    /api/scopes/{scopeId}/teams/{teamId}/members/{memberId}/automations/{scheduleId}
PUT    /api/scopes/{scopeId}/teams/{teamId}/members/{memberId}/automations/{scheduleId}
POST   .../{scheduleId}/reauthorize|pause|resume|run-now|retry-revocation
DELETE .../{scheduleId}

Preflight with {scheduleCron,scheduleTimezone,prompt,displayName,enabled}. Create/reauthorize must copy the current plan's permissionDigest and credentialPolicy.policyVersion, set credentialProvisioningKind=dedicated_scheduled_invocation_agent_key, and use stable, unique operationId plus idempotencyKey. Lifecycle actions also require those two operation identities. Never retry a lost mutation with new identities; reread the same owner resource first.

For owner-aware diagnostic reads through generic /api/schedules, use ownerKind=studio_member_automation plus ownerScopeId; add ownerTeamId for Team scope, and the full ownerScopeId + ownerTeamId + ownerMemberId tuple for a member or exact get. Legacy scopeId/teamId/memberId query names are invalid. Keep legacy generic schedules in a separate migration view; never mutate a Team automation through an ownerless legacy action.

active is credential health; enabled is firing. They are independent dimensions — do not report one as the other.

Fire and how the workflow gets the credential

Cron and run-now use the same active credential generation. Run-now proves a manual fire only; it never proves cron-origin execution.

Aevatar projects a borrowed DurableCallerCredentialRef into the workflow caller context. The raw Agent Key is not copied into workflow state. Every LLM, tool, and connector path that needs the caller credential resolves that reference through ISecretVault at the moment it is used, and resolution is fail-closed for an absent, expired, revoked, mismatched, or malformed reference.

So do not describe this path as one 300-second broker token minted at fire and shared for the whole run. That describes a generic schedule using a NyxID binding source — a different credential source with different lifetime semantics.

Lifecycle operations

  • Pause / resume. Pause disables future firing but preserves the active credential. Resume re-enables firing if the credential is still usable. Neither is a revoke or a reauthorization — never recreate or revoke a key to resume.
  • Update. Cron, timezone, prompt, display name, and enabled changes revalidate current authorization facts. An update never silently expands key grants or swaps the active credential. Authorization drift surfaces as an explicit reauthorization requirement.
  • Reauthorize (this is what a new external service dependency requires). Start from a new preflight and confirmation, provision a new dedicated key generation from the newly validated exact plan, and only after the replacement generation is committed revoke the old one. Never mutate an existing key in place to widen its authority.
  • Delete. The tombstone and revocation intent commit before external cleanup. NyxID key revocation and Vault secret revocation are independent durable tracks. The row stays visible as deleting / revocation_pending while either required track is incomplete. Retry reuses the original delete operation and idempotency identity plus fresh owner authority — it never synthesizes a new delete, reauthorization, or credential. Only completion of all required tracks lets the automation disappear.
  • Expiry and drift. An expired, missing, revoked, unresolvable, or authorization-mismatched key fails closed: the automation moves toward needs_authorization and future fire leases are canceled. It must never fall back to an interactive user bearer, a Host default, an inferred binding, an inferred service, or a wildcard grant.

Stable recovery

  • Lost create response → reread by exact owner and original operation identity; never create a second schedule with new identities.
  • authorization_plan_changed → rerun preflight before retrying.
  • needs_authorization → new preflight and explicit reauthorize.
  • revocation_pending → retry revocation with the original delete operation identity.
  • Missing owner binding or authorization catalog evidence → fail closed and report the prerequisite; never invent evidence or trigger projection repair.
  • TEAM_AUTOMATION_AUTHORIZATION_ROUTE_UNRESOLVED / tool authorization_catalog_route_unresolved → non-retryable 409. Preserve the sanitized refreshFailureCode and exact requiredUserServiceIds, stop retrying refresh/preflight, and fix or deactivate the unresolved configured route before trying again. A required service ID can be affected by a same-catalog active peer; it is not by itself proof of the offending row. Never delete or reconnect unrelated services.
  • Projection pending → report eventual visibility and the required version; never replay or prime projection from the query path.

Generic typed-service schedule (/api/schedules)

Everything below is the generic typed service-invocation resource. External callers cannot schedule a raw actor EventEnvelope; that target is retired and rejected. Never use an envelope as a fallback for a Team member.

You create a schedule that fires a published service on a cron expression, authenticated as you (the scope owner) through NyxID. Publish the service first (aevatar-service-publisher) — you need its identity, an endpoint, and the payload type.

Bootstrap

# Drive aevatar THROUGH the NyxID broker: it injects your scope_id claim AND auto-refreshes your
# token. A raw curl to the aevatar backend with ~/.nyxid/access_token resolves NO scope
# (scopeResolved:false) and the stored token expires — it is not a usable path.
# Prerequisite once: the `aevatar` service must be connected — `nyxid service add aevatar`.
# NOTE: the aevatar backend requires `Content-Type: application/json` on writes (POST/PUT) —
# omit it and every write returns HTTP 415 Unsupported Media Type. The helper sets it on
# every call (harmless on bodyless GETs), so the POST/PUT examples below work as written.
aev() { nyxid proxy request aevatar "$@" -H 'Content-Type: application/json'; }   # aev "<path>" [-m POST|PUT|DELETE] [-d '<json>'] [--stream]
scopeId=$(aev "api/studio/context" | jq -r .scopeId)

jq is only for convenience — any JSON reader works (replace | jq -r .scopeId with | python3 -c 'import sys,json;print(json.load(sys.stdin)["scopeId"])'). All calls go through the NyxID broker (nyxid proxy request aevatar), which injects your scope_id claim and auto-refreshes the token. Reminder: the scopeOwnerNyxId precondition below cannot be satisfied by a bare NyxID CLI token — it needs the owner's interactive console NyxID login (broker binding), or creation 400s.

Gather the target (one call: the scope services list)

GET /api/scopes/{scopeId}/services returns everything you need per service — copy it off the entry for your service:

aev "api/scopes/$scopeId/services" \
  | jq '.[] | {tenantId, appId, namespace, serviceId, defaultServingRevisionId, invokeReady,
               endpoints: [.endpoints[] | {endpointId, requestTypeUrl}]}'
  • identity — copy the explicit 4-tuple {tenantId, appId, namespace, serviceId} from the service read model or member published-service association. Never derive serviceId from memberId, a prefix, route position, or string equality.
  • endpointId + payloadTypeUrl — from endpoints[] (payloadTypeUrl = the endpoint's requestTypeUrl). A workflow member's default endpoint is chat with type.googleapis.com/aevatar.ai.ChatRequestEvent.
  • revisionId — use the service's defaultServingRevisionId. Required whenever you send payloadJson (see below).
  • payloadJson — the request body as a JSON string (or payloadBase64 for a packed proto). For a chat endpoint, {"prompt":"…"} is accepted.
  • Confirm invokeReady is true before scheduling — a schedule against a not-yet-serving service will fire into nothing.

Preview the cron first (no clock guessing)

aev "api/schedules/preview" -m POST \
  -d '{"cronExpression":"0 9 * * 1-5","timezone":"Asia/Shanghai","count":"5"}' | jq .

Returns the next N fire times so you can confirm the expression means what the user wants. Use a real IANA timezone; the engine has no implicit local time.

Precondition: the scope owner needs a NyxID owner (broker) binding

A scheduled service fire happens later, after your current token has expired, so the platform must be able to re-mint the scope owner's NyxID credential at fire time. That requires an authenticated NyxID owner binding (urn:nyxid:scope:broker_binding), established by signing in through the Aevatar console / studio NyxID login (a browser PKCE authorization_code flow → POST /api/auth/nyxid/finalize). A plain NyxID-CLI token is not sufficient. Create-time validation does a real token mint, so a missing/revoked binding fails fast at create with one of:

HTTP 400 — "Authenticated NyxID owner binding is required for scope owner schedule auth…" HTTP 400 — "NyxID binding was revoked for the scheduled subject. (Parameter 'configuration')"

Diagnose from the typed create/preflight error and the Aevatar read model. Never read a stored access token, construct an Authorization header, or call NyxID/Aevatar directly with curl. A clean console re-login (fully logged out first) refreshes a revoked binding — finalize replaces it on the revoked/stale probe path — so that usually clears it; an SSO-cached login may not re-run finalize.

There is no CLI / headless path to establish this binding (NyxID mints broker bindings only via the authorization_code grant; the only Aevatar writer is the browser finalize). Tracked at aevatarAI/aevatar#2491 — do not promise a CLI-only way to create a scopeOwnerNyxId schedule until it lands.

CLI-only alternative: skip the Aevatar scheduler entirely

For a recurring run without the browser console, don't use scopeOwnerNyxId scheduling. An explicitly authorized external timer may invoke the already-published member/team endpoint through NyxID using a dedicated minimum-authority API key kept in that timer's secret manager. Never print the key, put it in workflow YAML, export it into a shared shell history, or expose it in diagnostics. The member invoke endpoint carries scopeId in its path, so it runs even though a bare API key reports scopeResolved:false on the generic api/studio/context call. The same pattern works for event-driven external triggers such as Lark Base automation's "send HTTP request" action: store the NyxID API key as the external system's secret and POST to the explicit member/team invoke path. This is not Aevatar externalExposure; externalExposure is only needed when the workflow must be registered as a reusable NyxID connector/slug. Trade-off: the timer or event sender runs outside Aevatar (a cloud cron would live in Aevatar; this does not).

The binding-exchange fire-time credential lives 5 minutes — design the run around it

Scope of this section: generic /api/schedules using a NyxID binding source only. Read credentialSourceKind before applying any of it. If the run reports credentialSourceKind = scheduled_invocation_agent_key, none of the numbers below apply — jump to Diagnosing a scheduled-run credential failure.

For a binding-exchange source, at every fire Aevatar exchanges the stored broker binding for a fresh access token (OAuth token-exchange, subject_token_type=urn:nyxid:params:oauth:token-type:binding-id) and projects that one token into the run as its caller credential — minted once, shared by the whole run (aevatar: agents/Aevatar.GAgents.Channel.Identity/Broker/NyxIdRemoteCapabilityBroker.cs, src/platform/Aevatar.GAgentService.Infrastructure/Schedules/ScheduledServiceInvocationDispatchPort.cs). Broker-issued tokens are pinned to BROKER_ACCESS_TTL_SECS = 300 (NyxID backend/src/services/oauth_broker_service.rs) so a revoked binding stops working within 5 minutes without introspection. Deliberate design, not a bug.

Consequence: every NyxID-authenticated step in such a fired run must complete within ~5 minutes of fire. In a longer run, late steps failing with token_expired is the expected platform behavior — keep those scheduled runs short, front-load the NyxID-authenticated steps, or split long pipelines into separate schedules. Do not "fix" it by retrying the same run shape.

Diagnosing a scheduled-run credential failure

Identify the typed credential source before interpreting any 401 or token_expired. Gather the canonical path and owner tuple, credentialSourceKind, authorizationStatus, credentialExpiresAtUtc, credentialGeneration, stateVersion, lastAuthorizationErrorCode, revocationPending, nyxIdRevocationStatus, vaultRevocationStatus, and the exact run/tool failure and timestamp.

credentialSourceKindDiagnosis
nyxid_binding_exchangeThe 300 s broker TTL above is the right hypothesis. Confirm with the exchanged token's exp − iat or the repo constant, then fix run shape.
scheduled_invocation_agent_keyDo not diagnose a fixed five-minute broker expiry merely because the call was scheduled. Inspect key expiry, Vault resolution, reference integrity, committed caller authority, authorization fact, the exact service/node grants versus what the failing step actually called, credentialGeneration, and revocation state. Then look at the downstream service's own token. A token_expired six minutes after fire on this source is not explained by the 300 s constant — that constant belongs to a different credential class.

Token classes are not interchangeable — never quote one class's TTL for another. Your interactive login token lives for hours (JWT_ACCESS_TTL_SECS, a deployment config — code default is 900 s); a binding-exchange run credential lives 300 s (fixed constant); a dedicated scheduled-invocation Agent Key is Vault-held with a policy-governed expiry (a scheduled skill agent's default projected lifetime is ~90 days); NyxID API keys (nyxid api-key create) don't expire at all. When diagnosing any expiry, read the lifetime instead of recalling it: decode the JWT actually in hand and report exp − iat (numbers only — never print the token), cite the owning repo's constant, or read the automation's credentialExpiresAtUtc and credentialGeneration.

Never emit secret material in any report, log excerpt, artifact, or message: no raw Agent Key, bearer/access/refresh/delegation/service-account token, Vault reference or ciphertext, permission digest, unfiltered API-key inventory, or authorization header. Stable resource IDs may be reported for management or cleanup, but never as secret material and never to derive another identity.

Create the schedule

aev "api/schedules" -m POST -d "{
  \"displayName\": \"Weekday 9am run\",
  \"cronExpression\": \"0 9 * * 1-5\",
  \"timezone\": \"Asia/Shanghai\",
  \"enabled\": true,
  \"serviceInvocation\": {
    \"identity\": { \"tenantId\": \"<from-service-contract>\", \"appId\": \"<from-service-contract>\", \"namespace\": \"<from-service-contract>\", \"serviceId\": \"<published-service-id-from-contract>\" },
    \"endpointId\": \"chat\",
    \"payloadTypeUrl\": \"type.googleapis.com/aevatar.ai.ChatRequestEvent\",
    \"payloadJson\": $(jq -nc '{prompt:"do the thing"} | tojson'),
    \"revisionId\": \"<defaultServingRevisionId>\",
    \"auth\": { \"scopeOwnerNyxId\": { \"scope\": \"proxy\" } }
  }
}"

ScheduledDispatchConfigurationHttpRequest: cronExpression (required); displayName?, timezone?, enabled (default true), headers? (string map), and exactly one serviceInvocation target. Any external envelope target must be rejected.

payloadJson requires revisionId. If you supply payloadJson without a revisionId (and the service has no active serving revision), creation fails with 400 "payloadJson requires a revisionId; provide one explicitly or activate a serving revision." Pass the service's defaultServingRevisionId.

Workflow-member services: use payloadBase64, not payloadJson. A member-<id> service produced by a Studio bind (the common workflow path) carries a serving revision with no protocol descriptor, so payloadJson fails creation with 400 "payloadTypeUrl '…ChatRequestEvent' could not be resolved: revision '…' has no protocol descriptor set." The fix is to send the request as a packed proto in payloadBase64 instead — it bypasses the descriptor-based JSON encoding. The streaming invoke (…/invoke/chat:stream) accepts the {"prompt":"…"} shorthand via a shim, but the scheduler's typed path does not. For a ChatRequestEvent with prompt at field 1:

# python3 -c "import base64;print(base64.b64encode(bytes([0x0a,len(p:=b'do the thing')])+p).decode())"
# → swap the `payloadJson` line for:  "payloadBase64": "CgxkbyB0aGUgdGhpbmc=",

If your workflow ignores the prompt (e.g. a self-contained poll), any valid ChatRequestEvent payload triggers the run.

Auth (serviceInvocation.auth)

  • scopeOwnerNyxId: { scope } — fire as the scope owner, re-minting their NyxID at fire time. The right choice for owner-run schedules, but it requires the owner's broker binding (see Precondition above), otherwise creation 400s.
  • senderNyxId: { subject: { platform, externalUserId, tenant? }, scope } — fire as a specific external subject. Only when the schedule must run as someone other than the owner, and that subject already has a durable NyxID binding — otherwise the fire fails at credential-mint time.

Verify, then manage

sid=$(...)   # scheduleId from the create response
aev "api/schedules"            | jq '.[] | {scheduleId, displayName, cronExpression, enabled, nextFireUtc}'
aev "api/schedules/$sid"       | jq .
aev "api/schedules/$sid:run-now" -m POST   # fire once immediately to test
aev "api/schedules/$sid:disable" -m POST   # pause
aev "api/schedules/$sid:enable" -m POST    # resume
aev "api/schedules/$sid" -m PUT -d '{ ...updated configuration... }'
aev "api/schedules/$sid" -m DELETE         # remove

Note the action verbs use a colon (/{scheduleId}:run-now), not a slash.

After :run-now, confirm the fire actually executed — check the service's runs (GET /api/scopes/{scopeId}/services/{serviceId}/runs) or the observatory (GET /api/workflow/observatory/runs). A 2xx on the schedule call means accepted, not succeeded; a fire can still fail later at credential-mint or execution time, so read the run back before reporting success.

Next

  • Need to (re)publish the target service? aevatar-service-publisher.
  • Want the whole picture? aevatar-platform-map.

If you cannot complete a step server-side after a real attempt, hand the original request back to your caller rather than fabricating — see the fallback skill in this family.

Keep looking

Skills are one crate of 627,801. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.