Skip to content

Actor tips via reserved TIP key in the KVS #141

Description

@nicklamonov

Summary

Let an Actor surface short, human-readable advisory messages — "tips" — about its own run, using a reserved key-value store key (TIP) with the same lightweight convention as OUTPUT. No new platform APIs or schema changes required; any consumer that already knows to read OUTPUT can equally read TIP.

Motivation

Actors sometimes know something useful about a run that isn't itself a result:

  • "You pointed Start URLs at instagram.com — there's a specialized Actor built for scraping that site."
  • "You set maxItems to 1 but maxConcurrency to 50 — these don't interact the way you might expect." (this might be more valid for other actors though)

Today there's no place to put this. It doesn't belong in the dataset (a tip isn't a data row and would corrupt exports/schema validation), and there's no existing "advisory" channel on the KVS. This proposal gives Actors a standard, zero-infrastructure way to emit that message, and gives any downstream reader (Console, MCP tool wrapper, apify-client, custom scripts) a predictable place to look for it.

Proposed solution

  • Reserve a KVS key named TIP (naming TBD — see Open Questions), written via the SDK the same way OUTPUT is today:
await Actor.setValue('TIP', {
    message: 'Start URL matches a site with a dedicated Actor: apify/website-content-crawler.',
    level: 'info', // e.g. info | warning
});
  • No schema is enforced platform-side, matching the OUTPUT precedent — the shape above is a suggested convention, not a contract.
  • Readers fetch it exactly like any other KVS record: GET /v2/key-value-stores/:id/records/TIP, or via client.keyValueStore(id).getRecord('TIP').
  • Consumers decide what to do with it. In particular, an MCP-tool wrapper around Actor runs can prepend the tip as a content text block ahead of the dataset-items result, since content is the part MCP clients reliably forward into model context.

What this does and doesn't cover

  • ✅ Actor-authored tips (contradictory inputs, ecosystem suggestions, anything the Actor's own code can detect).
  • ❌ Platform-generated tips (e.g. "this run OOM'd, try more memory") — the Actor process can't reliably self-report if it was killed, so that case needs a separate platform-side writer feeding the same key, or a different delivery route entirely. Out of scope for this proposal.

Example end-to-end flow

  1. Actor code detects an issue during a run and calls Actor.setValue('TIP', {...}).
  2. Run finishes; the KVS record persists as normal.
  3. A consumer (e.g. the MCP server wrapping this Actor as a tool) fetches the TIP record after the run completes and surfaces it however fits — inline text before results, a Console banner, etc.

Open questions

  • Naming. TIP vs. TIPS (singular vs. list-shaped) vs. something else — also needs to avoid colliding with the existing "Actor Issues" feature conceptually.
    • Recommendation: TIP
  • Single value vs. list. Should this support multiple tips per run, or just the latest overwrite (like statusMessage)?
    • Recommendation: Single value
  • Suggested schema. Do we publish a recommended shape (message, level, maybe code) so consumers can rely on some structure, or leave it fully freeform like OUTPUT?
  • Discoverability. How do consumers know an Actor supports tips at all — documentation convention only, or something declared in actor.json?
    • Will be decided after implementation as next step.

Non-goals

  • No changes to apify-core, the Run entity, or dataset-item response shapes.
  • No guarantee of visibility outside consumers that explicitly choose to read the TIP key.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions