Skip to content

feat: add actor-orchestrator-skill - #90

Open
metalwarrior665 wants to merge 2 commits into
mainfrom
feat/actor-orchestrator-skill
Open

metalwarrior665 wants to merge 2 commits into
mainfrom
feat/actor-orchestrator-skill

Conversation

@metalwarrior665

Copy link
Copy Markdown
Member

No description provided.

@B4nan

B4nan commented Sep 22, 2026

Copy link
Copy Markdown
Member

Compared this against what apify-orchestrator does (details in Slack: https://apify.slack.com/archives/C0C2J6FE4QJ/p1790091211275669). A few gaps in the "must have" section that agent-written code will get wrong on its own:

  • Orphan window. The suggested loop saves the run id after start() returns, but useState only persists on interval and on migrating. A hard kill (OOM, timeout) in between orphans the child and a new one gets started on resurrection. Worth calling out; an explicit Actor.setValue() right after start() narrows it.
  • State keys for fan-out. The only state example is state.thisActorRunId = run.id, a single slot. For parallel runs the agent will likely do state.runIds.push(run.id) inside a Promise.all, and after a restart mid fan-out that doesn't say which chunk each run belongs to or which chunks never started. The skill should say: derive a deterministic key per work item (state.runs[chunkKey] = runId) and check it before starting.
  • Failed children. Not covered. Should a failed child be retried, and how many times? The library retries, the skill says nothing.
  • "Only fail if it seems we are deadlocked" is undefined, so the agent will pick a number. A concrete rule (give up after N minutes with no progress) would help.
  • Resurrect vs restart. The skill says to resurrect aborted children on parent resurrection, the library starts new runs. Resurrect is the better default, but it should also cover TIMED-OUT children, and it needs saying that a FAILED child cannot be resurrected into success and has to be restarted.
  • lukaskrivka/dedup-datasets-limited-permissions is hardcoded as the processing Actor. If it's the intended tool it should probably live under apify/, or be phrased as a suggestion rather than a requirement.

Most of these should end up in the SDK eventually, but until then the skill is the spec, so it should be explicit about them.

@metalwarrior665

Copy link
Copy Markdown
Member Author

Thanks for the review, will update

Orphan window

Makes sense as additional safety.

State keys for fan-out

I think agents are good enough to do this right. We can measure later. I always try to give less context rather than more.

Failed children

I don't agree with default auto retry, think that is a bad call from the lib. This might be a separate skill. This skills only focuses on how to write the Actor calling but doesn't teach how to choose Actors, how to replace them etc. In this case, the agent should check the error and decide if to adjust something or swap to different Actor, not make assuptions upfront. I will add a small note.

"Only fail if it seems we are deadlocked"

Can give hint but if it happens, agent should discuss with user.

Resurrect vs restart.

Not sure why lib starts new runs. Timed out and failed should not be handled without prior agent check, will mention

lukaskrivka/dedup-datasets-limited-permissions is hardcoded as the processing Actor

It is battle tested, no reason to suggest more of them. Moving to Apify makes sense.

@gullmar

gullmar commented Sep 23, 2026

Copy link
Copy Markdown

I don't agree with default auto retry, think that is a bad call from the lib.

The library retries only if it fails to start a run due to lack of memory/concurrency (opt out). It doesn't retry failed runs, that's up to the orchestrating user.

Resurrect vs restart.

I agree that resurrection would be the best option. The library doesn't do it just because nobody requested it so far.

Some observations:

  • The Sequential pipeline suggests taking the first run's output and use it to generate the second run's input. This was actually one of my first use cases and, in practice, it caused reaching the API limit (9MB) when starting the second run, since a run's output can be huge. That's why the library supports splitting the input in batches and starting multiple runs instead of one. I'm not sure how common this edge case is and if it should be documented in the skill.
  • What does the orchestrator see when a child run stops due to reaching maxTotalChargeUsd? Maybe the skill should tell the agent how to handle that case.
  • Maybe we could suggest to type and validate the children outputs with Zod, based on their current dataset schema and the needs of the orchestrator? (Just type the required fields and allow additional ones)

@metalwarrior665

Copy link
Copy Markdown
Member Author

his was actually one of my first use cases and, in practice, it caused reaching the API limit (9MB) when starting the second run, since a run's output can be huge

I think this will be very rare, you can run tens of thousands input URLs still ok. Normally you don't pass around full output, you extract with fields and then pass only what is needed. Sure there will be cases where you need to start multiple child runs but I would probably let the agent to discover how to handle it. I can add just note to split on when it thinks it can reach 9 MB.

What does the orchestrator see when a child run stops due to reaching maxTotalChargeUsd

It doesn't really need to see anything. The run normally stops and it continues to process the data. The agent will expect this because it knows the price of events. Imagine that user starts the orchestrator with $5. The agent will build the orchestrator so that the budget is distributed for each step to follow the other. E.g. Actor 1 will get $1 to produce 1000 restuls, those are passed to Actor 2 that gets $3 to convert 1000 input to 3000 results and last one gts $1.

Maybe we could suggest to type and validate the children outputs with Zod, based on their current dataset schema and the needs of the orchestrator?

It probably only cares about few fields being present but yeah it should double check that.

Comment on lines +51 to +52
- Hitting account memory limit throw with `error.type === 'actor-memory-limit-exceeded'`
- Hitting concurrent runs limit throw with `error.type === 'concurrent-runs-limit-exceeded'`

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nit:

Suggested change
- Hitting account memory limit throw with `error.type === 'actor-memory-limit-exceeded'`
- Hitting concurrent runs limit throw with `error.type === 'concurrent-runs-limit-exceeded'`
- Hitting account memory limit throws with `error.type === 'actor-memory-limit-exceeded'`
- Hitting concurrent runs limit throws with `error.type === 'concurrent-runs-limit-exceeded'`

@patrikbraborec

Copy link
Copy Markdown
Collaborator

Hi, some parts are already discussed above, but I am sharing feedback on the skill based on my tests mentioned in the slack:

Retry a failed step, and say what was lost.

No guidance on retrying a child run that failed, or on reporting what a failed step lost. I am not sure, if we want to make this part of the skill.

Stream results from a running child

Every Actor that was built with the skill calls call() and then reads the dataset afterwards. Again, not sure if this should be handled in the skill. I think, if we see use case for this, we can handle it with the SDK.

Re-run one step alone

In the skill, we have explicitly "should not rerun started runs", but this will harm re-running one step, such as step 2 after fixing its transformation, while keeping step 1's results.

--

Claude Code reported more things, but I see these things as the most important - again, maybe some of them should be handled by SDK, or some of them are not important right now.

@metalwarrior665

Copy link
Copy Markdown
Member Author

I addressed the comments. I see work has already been done in some clients. Once that is merged across them, I will simplify this. For now, we can keep it as internal document.

@gullmar gullmar left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LGTM! Just a couple of observations.

Comment thread skills/apify-actor-orchestrator/SKILL.md
Comment thread skills/apify-actor-orchestrator/SKILL.md
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.

5 participants