Skip to content

feat(agent): crewai orchestrator#608

Merged
dylan-savage merged 9 commits into
developfrom
feat/crewai-orchestrator
Apr 7, 2026
Merged

feat(agent): crewai orchestrator#608
dylan-savage merged 9 commits into
developfrom
feat/crewai-orchestrator

Conversation

@dylan-savage
Copy link
Copy Markdown
Collaborator

@dylan-savage dylan-savage commented Apr 2, 2026

Summary

Context: We want power user's to be able to run agent frameworks to the degree of complexity that the framework provider intended. This is in addition to the option of running frameworks with minimal configuration. This PR addresses 1/2 processes available in crewai (the hierarchical process), and introduces the ability to configure your crews prompts manually by choosing advanced mode.

  • Two node types from one module — CrewDriver (single-agent Crew, agent_crewai://) and OrchestratorDriver (hierarchical multi-agent Crew, agent_crewai_orchestrator://), with the orchestrator fanning out crewai.describe to collect and wire up all connected sub-agents at runtime

  • Advanced mode config — both nodes expose an expert_mode toggle that conditionally reveals CrewAI-specific fields (role, goal, backstory, task_description, expected_output for agents; goal, backstory for the orchestrator manager)

  • CrewAI Control Interface:

  • This PR introduces a control plane (crewai invoke channel) that connects sub-agent nodes to an orchestrator. When the CrewAI Orchestrator runs, it fans out a describe call to every connected sub-agent, collects their role and task config, and assembles a hierarchical CrewAI Crew at runtime — each sub-agent using its own pipeline LLM and tools. The CrewAI node works standalone without an orchestrator and only participates in orchestration when wired up via the crewai channel.

Note:

  • Crew's sequential process will be implemented separately, as their is currently no intuitive way to build a sequential agent flow within our canvas.

Type

Testing

  • Tests added or updated
  • Tested locally
  • ./builder test passes

Checklist

  • Commit messages follow conventional commits
  • No secrets or credentials included
  • Wiki updated (if applicable)
  • Breaking changes documented (if applicable)

Linked Issue

Fixes #

Summary by CodeRabbit

  • New Features

    • Hierarchical multi-agent Orchestrator node that fans out to connected agents and synthesizes their outputs.
    • Agents can self-describe so the orchestrator auto-discovers and builds per-agent tasks.
    • Advanced agent configuration UI: role, goal, backstory, task description, expected output, and advanced-mode toggle.
  • Chores

    • Platform API extended with a crew-invoke control model to support orchestration interactions.

@github-actions github-actions Bot added module:server C++ engine and server components module:nodes Python pipeline nodes labels Apr 2, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 2, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Global state now exposes CrewAI agent/task fields parsed from connection config; CrewDriver refactored with CrewAgentBase and describe() API; OrchestratorDriver added to fan out to sub-agents and run hierarchical Crews; IInstance handles crewai.describe; new Pydantic IInvokeCrew models and service schemas added; exports updated.

Changes

Cohort / File(s) Summary
Core Driver & Base
nodes/src/nodes/agent_crewai/crewai.py
Added CrewAgentBase for LLM/tool binding and safety helpers; refactored CrewDriver to accept public config fields (role, task_description, goal, backstory, expected_output), return (final_text, result), and expose describe(); added OrchestratorDriver to fan out crewai.describe, assemble per-node Agents/Tasks, build a hierarchical Crew, and synthesize results.
Global State & Init
nodes/src/nodes/agent_crewai/IGlobal.py
Parses connConfig into public attributes (role, task_description, goal, backstory, expected_output); instantiates OrchestratorDriver when logicalType is agent_crewai_orchestrator, otherwise CrewDriver; endGlobal() resets the new fields plus agent/process.
Instance Invoke Handling
nodes/src/nodes/agent_crewai/IInstance.py
Intercepts op == "crewai.describe": calls IGlobal.agent.describe(self) when available and appends/returns descriptor(s) into param.agents; preserves existing tool.* handling and fallback.
Node Service Schema (Standard)
nodes/src/nodes/agent_crewai/services.json
Added "crewai" to classType; removed agent_crewai.profile; added advanced_mode, role, goal, backstory, task_description, expected_output and headers; updated agent_crewai.default and UI shape to expose new default object.
Orchestrator Node Schema
nodes/src/nodes/agent_crewai/services.orchestrator.json
New orchestrator node (agent_crewai_orchestrator://) defining preconfig, required connections (llm + crewai), fields (instructions, advanced_mode, goal, backstory), and UI pipe shape exposing agent_crewai_orchestrator.default.
Control Models & Exports
packages/server/engine-lib/rocketlib-python/lib/rocketlib/types.py, .../__init__.py
Added IInvokeCrew Pydantic model with Describe and DescribeResponse for crewai.describe; exported IInvokeCrew from rocketlib package __init__.

Sequence Diagram

sequenceDiagram
    participant Client
    participant Orchestrator as OrchestratorDriver
    participant SubA as Sub-Agent A (CrewDriver)
    participant SubB as Sub-Agent B (CrewDriver)
    participant Manager as Manager Agent
    participant Crew as CrewAI Crew

    Client->>Orchestrator: _run(prompt)
    Orchestrator->>SubA: invoke crewai.describe
    SubA-->>Orchestrator: DescribeResponse(role,task_description,invoke,node_id)
    Orchestrator->>SubB: invoke crewai.describe
    SubB-->>Orchestrator: DescribeResponse(...)

    Orchestrator->>Orchestrator: Build Agent+Task per descriptor
    Orchestrator->>Manager: create manager agent (goal, backstory)
    Orchestrator->>Crew: construct hierarchical Crew(manager, agents)
    Orchestrator->>Crew: run crew with user request
    Crew-->>Orchestrator: result_text
    Orchestrator-->>Client: synthesized result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • jmaionchi
  • Rod-Christensen
  • ryan-t-christensen

Poem

🐇 I parsed the props and set each role,
I nudged the crew to play their goal.
They shout, they scope, they share their part,
A manager hums, the answers start. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 47.37% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(agent): crewai orchestrator' accurately captures the main feature addition—the introduction of a CrewAI orchestrator node for hierarchical multi-agent workflows.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/crewai-orchestrator

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@nodes/src/nodes/agent_crewai/crewai.py`:
- Around line 400-406: The _run method is too large (53 statements); extract
logical blocks into small helpers to reduce complexity: create
_discover_sub_agents(self, ctx) to isolate discovery/filtering of sub-agent
configs, _build_sub_agent(self, config, host, ctx) to construct and return a
SubAgent instance from a config, and _build_manager(self, agents, host, ctx) to
assemble the manager/coordinator and its initial state; then replace the
corresponding code blocks in _run with calls to these helpers and ensure any
local variables they need are passed in and returned explicitly (update imports
and tests if necessary).
- Around line 437-443: The current code swallows exceptions from
pSelf.instance.invoke('crewai', req, nodeId=node_id) which hides failures;
modify the try/except around pSelf.instance.invoke to catch Exception as e and
log the error (including exception message/stack) using the node's logger (e.g.,
pSelf.logger or similar) before continuing so discovery still appends req.agents
into descriptors; ensure you keep the subsequent for agent_desc in req.agents
loop unchanged and do not rethrow so behavior remains resilient while providing
diagnostics.
- Around line 279-280: The import of extract_prompt is invalid; replace it with
the existing utility extract_text from ai.common.agent._internal.utils (or
publicly exported module) and change the usage so prompt =
extract_text(agent_input.question) if hasattr(agent_input, 'question') else ''
(or implement a small wrapper named extract_prompt in the same module if you
truly need different behavior). Update the import statement that currently names
extract_prompt and the subsequent call site that uses
extract_prompt(agent_input.question) to use extract_text (or the newly defined
extract_prompt) so the code no longer raises an ImportError at runtime.

In `@nodes/src/nodes/agent_crewai/IInstance.py`:
- Around line 54-57: The silent except around the Pydantic field assignment
(param.agents = existing) should be replaced with a guarded catch that logs the
failure at debug level instead of swallowing it: change the bare except to
"except Exception as e" and call a module or class logger (e.g., logger.debug or
self.logger.debug) with a concise message referencing "param.agents" and
"existing" and include the exception info (e) and optionally traceback; keep the
defensive behavior (do not re-raise) if the intent is to continue on Pydantic
assignment errors.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: caec0a1e-ad6f-4920-83ba-40a923928542

📥 Commits

Reviewing files that changed from the base of the PR and between ac0b1ec and 19ddd05.

📒 Files selected for processing (7)
  • nodes/src/nodes/agent_crewai/IGlobal.py
  • nodes/src/nodes/agent_crewai/IInstance.py
  • nodes/src/nodes/agent_crewai/crewai.py
  • nodes/src/nodes/agent_crewai/services.json
  • nodes/src/nodes/agent_crewai/services.orchestrator.json
  • packages/server/engine-lib/rocketlib-python/lib/rocketlib/__init__.py
  • packages/server/engine-lib/rocketlib-python/lib/rocketlib/types.py

Comment thread nodes/src/nodes/agent_crewai/crewai.py Outdated
Comment thread nodes/src/nodes/agent_crewai/crewai.py
Comment thread nodes/src/nodes/agent_crewai/crewai.py
Comment thread nodes/src/nodes/agent_crewai/IInstance.py
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@nodes/src/nodes/agent_crewai/services.orchestrator.json`:
- Around line 84-87: The properties array for agent_crewai_orchestrator.default
is missing the advanced-mode fields, so add the advanced keys ("goal" and
"backstory") to the "properties" list for agent_crewai_orchestrator.default and
ensure the UI/persistence layer references those same keys; specifically update
the agent_crewai_orchestrator.default.properties to include "goal" and
"backstory" so the conditional references to goal and backstory will render and
be saved with the active profile object.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6a58ec6a-313b-4fda-8197-7d6d26659367

📥 Commits

Reviewing files that changed from the base of the PR and between 19ddd05 and 5911da2.

📒 Files selected for processing (2)
  • nodes/src/nodes/agent_crewai/services.json
  • nodes/src/nodes/agent_crewai/services.orchestrator.json

Comment thread nodes/src/nodes/agent_crewai/services.orchestrator.json Outdated
stepmikhaylov
stepmikhaylov previously approved these changes Apr 2, 2026
@Rod-Christensen Rod-Christensen changed the title Feat/crewai orchestrator feat(agent): crewai orchestrator Apr 2, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
nodes/src/nodes/agent_crewai/crewai.py (2)

102-109: ⚠️ Potential issue | 🔴 Critical

Method signature violates the abstract base class contract.

AgentBase._bind_framework_tools requires a log_tool_call: Callable[..., None] parameter (see packages/ai/src/ai/common/agent/agent.py:307-316), but this override removes it. If any polymorphic caller passes log_tool_call=... (as the LangChain driver does at nodes/src/nodes/agent_langchain/langchain.py:262-268), this will raise TypeError.

Add the parameter to maintain the contract, even if unused:

🔧 Suggested fix
 def _bind_framework_tools(
     self,
     *,
     host: AgentHost,
     tool_descriptors: List[ToolsBase.ToolDescriptor],
     invoke_tool: Callable[..., Any],
+    log_tool_call: Callable[..., None],  # noqa: ARG002
     ctx: Dict[str, Any],
 ) -> List[Any]:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nodes/src/nodes/agent_crewai/crewai.py` around lines 102 - 109, The
_bind_framework_tools method currently removes the required log_tool_call
parameter from the AgentBase contract; restore the parameter signature by adding
log_tool_call: Callable[..., None] to _bind_framework_tools (keeping the
existing params host, tool_descriptors, invoke_tool, ctx) so the override
matches AgentBase._bind_framework_tools; accept and optionally ignore
log_tool_call inside the method body to preserve polymorphism with callers
(e.g., LangChain driver) that pass log_tool_call.

229-284: ⚠️ Potential issue | 🟠 Major

Task description from config is used exclusively; docstring contract violated.

The agent_input parameter is accepted but unused in _run (Ruff ARG002). The docstring explicitly states "If task_description is blank the incoming prompt is used as the task," but line 278 does task_text = self._task_description or '', which discards the incoming prompt entirely. This contradicts the documented behavior.

The fix should incorporate the incoming prompt when the config-provided task_description is empty:

🔧 Suggested fix
-        task_text = self._task_description or ''
+        prompt = _safe_str(agent_input.question.getPrompt() if hasattr(agent_input, 'question') else '')
+        task_text = self._task_description or prompt or 'Complete the user request.'

This pattern is already used in the orchestrator variant (line 412) and across other agent drivers (langchain, deepagent, rocketride).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nodes/src/nodes/agent_crewai/crewai.py` around lines 229 - 284, The _run
method currently ignores the agent_input parameter and always uses
self._task_description, violating the docstring; update the task_text assignment
in _run to fall back to the incoming prompt from agent_input (e.g., use
agent_input.prompt or agent_input.input_text depending on the AgentInput shape)
when self._task_description is empty, then pass that through _escape_braces as
before (replace the existing line setting task_text and ensure agent_input is
referenced so ARG002 is resolved); verify use in Task(description=...) still
works with the new task_text.
♻️ Duplicate comments (1)
nodes/src/nodes/agent_crewai/crewai.py (1)

489-498: ⚠️ Potential issue | 🟡 Minor

Sub-agent goal and backstory configs are not propagated through orchestration.

CrewDriver stores _goal and _backstory from expert_mode config and uses them in standalone mode. However, describe() only returns role and task_description. When the orchestrator builds sub-agents, it hardcodes _DEFAULT_GOAL and _DEFAULT_BACKSTORY for all, discarding the sub-agents' individual expert_mode configuration.

Either document this as intentional, or extend IInvokeCrew.DescribeResponse to include goal and backstory fields so custom values can be propagated.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nodes/src/nodes/agent_crewai/crewai.py` around lines 489 - 498, The
orchestrator currently ignores per-agent expert_mode goal/backstory by
hardcoding _DEFAULT_GOAL/_DEFAULT_BACKSTORY when constructing Agent; extend
IInvokeCrew.DescribeResponse to include goal and backstory, update
CrewDriver.describe() to return these fields (falling back to defaults if
unset), and change the orchestrator code that builds Agent (the block
constructing Agent with role=d.role, tools=sub_tools, llm=sub_llm, etc.) to use
the returned describe().goal and describe().backstory instead of
_DEFAULT_GOAL/_DEFAULT_BACKSTORY so each sub-agent preserves its expert_mode
configuration (alternatively, document this behavior explicitly if intentional).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@nodes/src/nodes/agent_crewai/crewai.py`:
- Around line 102-109: The _bind_framework_tools method currently removes the
required log_tool_call parameter from the AgentBase contract; restore the
parameter signature by adding log_tool_call: Callable[..., None] to
_bind_framework_tools (keeping the existing params host, tool_descriptors,
invoke_tool, ctx) so the override matches AgentBase._bind_framework_tools;
accept and optionally ignore log_tool_call inside the method body to preserve
polymorphism with callers (e.g., LangChain driver) that pass log_tool_call.
- Around line 229-284: The _run method currently ignores the agent_input
parameter and always uses self._task_description, violating the docstring;
update the task_text assignment in _run to fall back to the incoming prompt from
agent_input (e.g., use agent_input.prompt or agent_input.input_text depending on
the AgentInput shape) when self._task_description is empty, then pass that
through _escape_braces as before (replace the existing line setting task_text
and ensure agent_input is referenced so ARG002 is resolved); verify use in
Task(description=...) still works with the new task_text.

---

Duplicate comments:
In `@nodes/src/nodes/agent_crewai/crewai.py`:
- Around line 489-498: The orchestrator currently ignores per-agent expert_mode
goal/backstory by hardcoding _DEFAULT_GOAL/_DEFAULT_BACKSTORY when constructing
Agent; extend IInvokeCrew.DescribeResponse to include goal and backstory, update
CrewDriver.describe() to return these fields (falling back to defaults if
unset), and change the orchestrator code that builds Agent (the block
constructing Agent with role=d.role, tools=sub_tools, llm=sub_llm, etc.) to use
the returned describe().goal and describe().backstory instead of
_DEFAULT_GOAL/_DEFAULT_BACKSTORY so each sub-agent preserves its expert_mode
configuration (alternatively, document this behavior explicitly if intentional).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: b1248063-7a7f-484a-aed6-7a89ba505f90

📥 Commits

Reviewing files that changed from the base of the PR and between 5911da2 and ec2e3e1.

📒 Files selected for processing (1)
  • nodes/src/nodes/agent_crewai/crewai.py

@ryan-t-christensen
Copy link
Copy Markdown
Collaborator

@dylan-savage is the orchestrator node necessary - or can it just be an advanced toggle? I can sync with you on putting in some stronger UI/UX feedback?

stepmikhaylov
stepmikhaylov previously approved these changes Apr 6, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
nodes/src/nodes/agent_crewai/crewai.py (2)

167-185: ⚠️ Potential issue | 🟠 Major

Read inputSchema from object-backed tool descriptors too.

This block already supports both dict-style and attribute-style descriptors for name/description, but inputSchema is only loaded from dicts. If discover_tools() yields ToolDescriptor objects here, every structured tool falls back to _ToolInput, so CrewAI loses the real parameter names and multi-parameter tool calls stop matching the host schema.

💡 Minimal fix
-            input_schema = td.get('inputSchema') if isinstance(td, dict) else None
+            input_schema = (
+                td.get('inputSchema')
+                if isinstance(td, dict)
+                else getattr(td, 'inputSchema', None)
+            )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nodes/src/nodes/agent_crewai/crewai.py` around lines 167 - 185, The loop
building HostTool instances reads inputSchema only from dict-style descriptors,
causing object-backed descriptors to lose structured args; update the
input_schema extraction in the tools loop to also read the attribute form (e.g.,
getattr(td, 'inputSchema', None) or the appropriate attribute name on
ToolDescriptor) when td is not a dict so _make_args_schema receives the real
schema and HostTool(name=..., description=..., args_schema=...) preserves
parameter names for multi-parameter tools.

236-289: ⚠️ Potential issue | 🔴 Critical

Pass the incoming question into standalone Crew execution.

agent_input is never used when building the task, and crew.kickoff() is called without any inputs. As written, a standalone agent_crewai:// node can end up executing only the configured task text or the placeholder 'Complete the user request.', without ever seeing the actual user prompt.

🛠️ Suggested fix
         run_id = ctx.get('run_id', '')
+        prompt = _safe_str(agent_input.question.getPrompt() if hasattr(agent_input, 'question') else '')
         debug('agent_crewai driver _run start run_id={}'.format(run_id))
@@
-        task_text = self._task_description or ''
+        task_text = self._task_description or ''
+        if not task_text:
+            task_text = prompt or ''
+        elif prompt:
+            task_text = f'{task_text}\n\nUser request: {prompt}'
@@
-            result = crew.kickoff()
+            result = crew.kickoff(inputs={'user_request': prompt} if prompt else {})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nodes/src/nodes/agent_crewai/crewai.py` around lines 236 - 289, The task
never receives the incoming prompt because agent_input is unused and Crew is
kicked off without inputs; update the Task creation and Crew kickoff to pass the
incoming agent_input into the execution: if agent_input (or the node's incoming
question) is non-empty, use it as the Task.description (or concatenate/prepend
it to desc) when constructing Task (symbol: Task) and pass it into the Crew
kickoff call (symbol: crew.kickoff) via the appropriate inputs argument so the
agent sees the actual user prompt during standalone agent_crewai:// runs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@nodes/src/nodes/agent_crewai/crewai.py`:
- Around line 197-227: describe() currently only returns role and
task_description so goal, backstory and expected_output saved in __init__ are
not propagated; update describe (the CrewDriver.describe / DescribeResponse
creation) to include self._goal, self._backstory and self._expected_output in
the IInvokeCrew.DescribeResponse (alongside role, task_description, node_id,
invoke) so the orchestrator receives and rebuilds sub-agents with the actual
advanced config values.

---

Outside diff comments:
In `@nodes/src/nodes/agent_crewai/crewai.py`:
- Around line 167-185: The loop building HostTool instances reads inputSchema
only from dict-style descriptors, causing object-backed descriptors to lose
structured args; update the input_schema extraction in the tools loop to also
read the attribute form (e.g., getattr(td, 'inputSchema', None) or the
appropriate attribute name on ToolDescriptor) when td is not a dict so
_make_args_schema receives the real schema and HostTool(name=...,
description=..., args_schema=...) preserves parameter names for multi-parameter
tools.
- Around line 236-289: The task never receives the incoming prompt because
agent_input is unused and Crew is kicked off without inputs; update the Task
creation and Crew kickoff to pass the incoming agent_input into the execution:
if agent_input (or the node's incoming question) is non-empty, use it as the
Task.description (or concatenate/prepend it to desc) when constructing Task
(symbol: Task) and pass it into the Crew kickoff call (symbol: crew.kickoff) via
the appropriate inputs argument so the agent sees the actual user prompt during
standalone agent_crewai:// runs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 756777ed-8fc5-4b4d-b2dc-72986e93aeea

📥 Commits

Reviewing files that changed from the base of the PR and between ec2e3e1 and 99cc048.

📒 Files selected for processing (3)
  • nodes/src/nodes/agent_crewai/crewai.py
  • nodes/src/nodes/agent_crewai/services.json
  • packages/server/engine-lib/rocketlib-python/lib/rocketlib/__init__.py

Comment thread nodes/src/nodes/agent_crewai/crewai.py
dylan-savage and others added 7 commits April 6, 2026 12:43
Add goal, backstory, expected_output, max_iter to agent_crewai (CrewDriver)
and goal, backstory, max_iter to agent_crewai_orchestrator (OrchestratorDriver).
All fields fall back to existing defaults when blank/zero.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@dylan-savage dylan-savage force-pushed the feat/crewai-orchestrator branch from 99cc048 to 56555e9 Compare April 6, 2026 19:46
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
nodes/src/nodes/agent_crewai/crewai.py (1)

244-284: ⚠️ Potential issue | 🔴 Critical

Pass the user request into the standalone Crew.

This path never incorporates agent_input.question, so standalone agent_crewai:// runs can execute with only the static task_description or the generic fallback. That means the actual user prompt can be dropped entirely, and it also contradicts the task_description description in nodes/src/nodes/agent_crewai/services.json.

🛠️ Suggested patch
         run_id = ctx.get('run_id', '')
+        prompt = _safe_str(agent_input.question.getPrompt() if hasattr(agent_input, 'question') else '')
         debug('agent_crewai driver _run start run_id={}'.format(run_id))
@@
         task_text = self._task_description or ''
+        if not task_text:
+            task_text = prompt or 'Complete the user request.'
+        elif prompt:
+            task_text = f'{task_text}\n\nUser request: {prompt}'
 
         desc = _escape_braces(task_text)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nodes/src/nodes/agent_crewai/crewai.py` around lines 244 - 284, The task
description passed to the standalone Crew never includes the runtime user prompt
(agent_input.question), so when creating Task (task_obj) the actual user request
can be lost; update the logic that builds task_text (used to create
Task.description) to incorporate agent_input.question when present—e.g., merge
or append agent_input.question with self._task_description/_task_description
fallback or prefer agent_input.question if provided—so Task(description=...)
always reflects the runtime user request before constructing task_obj.
♻️ Duplicate comments (1)
nodes/src/nodes/agent_crewai/crewai.py (1)

211-227: ⚠️ Potential issue | 🟠 Major

Don't drop expert-mode sub-agent settings during orchestration.

nodes/src/nodes/agent_crewai/IGlobal.py now loads goal, backstory, and expected_output, but describe() only sends role/task_description and Lines 489-510 rebuild every sub-agent with hardcoded defaults. Once a CrewAI node is connected on the crewai channel, its advanced config is silently discarded.

🛠️ Suggested patch
         return IInvokeCrew.DescribeResponse(
             role=self._role,
             task_description=self._task_description,
+            goal=self._goal,
+            backstory=self._backstory,
+            expected_output=self._expected_output,
             node_id=node_id,
             invoke=pSelf,
         )
@@
             agent_obj = Agent(
                 role=d.role,
-                goal=_DEFAULT_GOAL,
-                backstory=_DEFAULT_BACKSTORY,
+                goal=getattr(d, 'goal', '') or _DEFAULT_GOAL,
+                backstory=getattr(d, 'backstory', '') or _DEFAULT_BACKSTORY,
                 tools=sub_tools,
                 llm=sub_llm,
                 verbose=False,
@@
             task_obj = Task(
                 description=task_desc,
-                expected_output=_DEFAULT_EXPECTED_OUTPUT,
+                expected_output=getattr(d, 'expected_output', '') or _DEFAULT_EXPECTED_OUTPUT,
                 agent=agent_obj,
             )

I’d also add these three attributes to packages/server/engine-lib/rocketlib-python/lib/rocketlib/types.py:IInvokeCrew.DescribeResponse so the transport schema matches the runtime payload.

Also applies to: 489-510

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nodes/src/nodes/agent_crewai/crewai.py` around lines 211 - 227, The
describe() method for CrewAI currently only returns role and task_description,
causing expert-mode sub-agent settings (goal, backstory, expected_output) to be
dropped during orchestration; update describe (the method named describe in
agent_crewai/crewai.py) to include goal, backstory, and expected_output in the
IInvokeCrew.DescribeResponse payload and ensure the code that rebuilds
sub-agents (the block that reconstructs sub-agents from the DescribeResponse)
consumes those three fields instead of using hardcoded defaults; also update the
transport schema type IInvokeCrew.DescribeResponse in rocketlib/types.py to
include goal, backstory, and expected_output so runtime and schema match.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@nodes/src/nodes/agent_crewai/IInstance.py`:
- Around line 45-59: The crewai.describe branch only reads/writes param.agents
via attribute access so dict/IDict payloads (where op is from param.get or
getattr) don't accumulate responders; update the branch around where op is
computed to read existing = param.get('agents') if isinstance(param, dict) else
getattr(param, 'agents', None) and when appending set the value back using
param['agents'] = existing for mappings or param.agents = existing for
attribute-style objects (keeping the existing try/except behavior), ensuring
both read and write paths handle mapping and attribute payloads before
returning.

---

Outside diff comments:
In `@nodes/src/nodes/agent_crewai/crewai.py`:
- Around line 244-284: The task description passed to the standalone Crew never
includes the runtime user prompt (agent_input.question), so when creating Task
(task_obj) the actual user request can be lost; update the logic that builds
task_text (used to create Task.description) to incorporate agent_input.question
when present—e.g., merge or append agent_input.question with
self._task_description/_task_description fallback or prefer agent_input.question
if provided—so Task(description=...) always reflects the runtime user request
before constructing task_obj.

---

Duplicate comments:
In `@nodes/src/nodes/agent_crewai/crewai.py`:
- Around line 211-227: The describe() method for CrewAI currently only returns
role and task_description, causing expert-mode sub-agent settings (goal,
backstory, expected_output) to be dropped during orchestration; update describe
(the method named describe in agent_crewai/crewai.py) to include goal,
backstory, and expected_output in the IInvokeCrew.DescribeResponse payload and
ensure the code that rebuilds sub-agents (the block that reconstructs sub-agents
from the DescribeResponse) consumes those three fields instead of using
hardcoded defaults; also update the transport schema type
IInvokeCrew.DescribeResponse in rocketlib/types.py to include goal, backstory,
and expected_output so runtime and schema match.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 860936ad-7a52-4b58-aa9f-3d33b23da8e9

📥 Commits

Reviewing files that changed from the base of the PR and between 99cc048 and 56555e9.

📒 Files selected for processing (7)
  • nodes/src/nodes/agent_crewai/IGlobal.py
  • nodes/src/nodes/agent_crewai/IInstance.py
  • nodes/src/nodes/agent_crewai/crewai.py
  • nodes/src/nodes/agent_crewai/services.json
  • nodes/src/nodes/agent_crewai/services.orchestrator.json
  • packages/server/engine-lib/rocketlib-python/lib/rocketlib/__init__.py
  • packages/server/engine-lib/rocketlib-python/lib/rocketlib/types.py

Comment thread nodes/src/nodes/agent_crewai/IInstance.py
dylan-savage and others added 2 commits April 6, 2026 14:37
goal, backstory, expected_output, and instructions were all loaded from
connConfig but not included in DescribeResponse, causing the manager to
silently fall back to hardcoded defaults for every sub-agent.

- Add goal, backstory, expected_output, instructions to DescribeResponse
- Populate them in CrewDriver.describe()
- Use d.goal/backstory/expected_output in ManagerDriver sub-agent build
- Append instructions to sub-agent backstory (substitutes for the
  run_agent() path that is bypassed in manager mode)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 6, 2026

No description provided.

@dylan-savage dylan-savage merged commit fcd779f into develop Apr 7, 2026
16 checks passed
@dylan-savage dylan-savage deleted the feat/crewai-orchestrator branch April 7, 2026 14:54
shashidharbabu pushed a commit that referenced this pull request Apr 7, 2026
* Feat: new control interface for crew, added crew orchestrator node

* orchestrator wip

* feat(agent_crewai): expose expert config fields for both node types

Add goal, backstory, expected_output, max_iter to agent_crewai (CrewDriver)
and goal, backstory, max_iter to agent_crewai_orchestrator (OrchestratorDriver).
All fields fall back to existing defaults when blank/zero.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: cleanup modified crew code

* Chore: Delete Crew readme

* chore: rename 'expert' mode to 'advanced' mode

* chore: remove dead code found by code rabbit

* Fix: Rename orchestrator to Manager; remove tool invoke from manager node

* fix: propagate sub-agent advanced config through crewai.describe()

goal, backstory, expected_output, and instructions were all loaded from
connConfig but not included in DescribeResponse, causing the manager to
silently fall back to hardcoded defaults for every sub-agent.

- Add goal, backstory, expected_output, instructions to DescribeResponse
- Populate them in CrewDriver.describe()
- Use d.goal/backstory/expected_output in ManagerDriver sub-agent build
- Append instructions to sub-agent backstory (substitutes for the
  run_agent() path that is bypassed in manager mode)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
ryan-t-christensen pushed a commit that referenced this pull request Apr 8, 2026
* Feat: new control interface for crew, added crew orchestrator node

* orchestrator wip

* feat(agent_crewai): expose expert config fields for both node types

Add goal, backstory, expected_output, max_iter to agent_crewai (CrewDriver)
and goal, backstory, max_iter to agent_crewai_orchestrator (OrchestratorDriver).
All fields fall back to existing defaults when blank/zero.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: cleanup modified crew code

* Chore: Delete Crew readme

* chore: rename 'expert' mode to 'advanced' mode

* chore: remove dead code found by code rabbit

* Fix: Rename orchestrator to Manager; remove tool invoke from manager node

* fix: propagate sub-agent advanced config through crewai.describe()

goal, backstory, expected_output, and instructions were all loaded from
connConfig but not included in DescribeResponse, causing the manager to
silently fall back to hardcoded defaults for every sub-agent.

- Add goal, backstory, expected_output, instructions to DescribeResponse
- Populate them in CrewDriver.describe()
- Use d.goal/backstory/expected_output in ManagerDriver sub-agent build
- Append instructions to sub-agent backstory (substitutes for the
  run_agent() path that is bypassed in manager mode)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai coderabbitai Bot mentioned this pull request Apr 13, 2026
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

module:nodes Python pipeline nodes module:server C++ engine and server components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants