Bundle multi-agent assets into exportable agents suite#1
Bundle multi-agent assets into exportable agents suite#1
Conversation
There was a problem hiding this comment.
Pull request overview
This PR bundles all existing multi-agent, automation, and AI artifacts into a single portable agents-suite/ directory for downstream migration.
Changes:
- Added
agents-suite/directory consolidating backend AI, shared kernel, automation platform, automation pipelines, eco-superai, and ng-era-platforms assets - Added
agents-suite/README.mddocumenting contents, source paths, and migration tips
Reviewed changes
Copilot reviewed 90 out of 2750 changed files in this pull request and generated 10 comments.
| File | Description |
|---|---|
agents-suite/README.md |
Top-level documentation for the bundle layout and migration guidance |
agents-suite/_shared/** |
Shared kernel: sandbox, container, environment, protocols |
agents-suite/automation-platform/** |
Multi-agent pipeline orchestrator, domain entities, engines, and tests |
agents-suite/automation/instant/** |
Instant execution scripts, configs, docs, and legacy artifacts |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "-H", | ||
| "Content-Type: application/json", | ||
| "-d", | ||
| str(config).replace("'", '"'), |
There was a problem hiding this comment.
Using Python's str() on a dict and then replacing single quotes with double quotes does not produce valid JSON. For example, Python's True/False/None will be serialized as True/False/None instead of true/false/null, and string values containing apostrophes will be mangled. Use json.dumps(config) instead to produce a properly serialized JSON string.
agents-suite/automation/instant/scripts/organize-instant-files.sh
Outdated
Show resolved
Hide resolved
| - id: "load_unified_pipeline" | ||
| action: "mcp.pipeline.load" | ||
| description: "Load the unified pipeline to ensure MCP methodology is applied." | ||
| inputs: |
There was a problem hiding this comment.
The description field on lines 28, 36, 53, and 70 is consistently mis-indented to be at the same level as the - id: list marker rather than being a child property of the step. This makes description a sibling of the step object rather than a property of it, and most YAML parsers will either error or silently ignore it. All description fields should be indented to align with action, inputs, etc.
agents-suite/automation/instant/scripts/run-instant-execution.sh
Outdated
Show resolved
Hide resolved
agents-suite/automation/instant/scripts/demo_instant_generation.py
Outdated
Show resolved
Hide resolved
agents-suite/automation/instant/scripts/demo_instant_generation.py
Outdated
Show resolved
Hide resolved
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…n.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…n.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 90 out of 2753 changed files in this pull request and generated 8 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Move the file | ||
| echo -e "${GREEN}✓ Moving${NC} $file -> $dest$filename" | ||
| mv "$file" "$dest$filename" | ||
| ((MOVED_COUNT++)) |
There was a problem hiding this comment.
The MOVED_COUNT increment is inside a while read loop fed by a subshell pipeline (find ... | ... | while read). In bash, pipe components run in subshells, so MOVED_COUNT increments are lost and the variable always remains 0 in the parent shell. The final summary will always report 0 moved files. To fix this, either use process substitution (while read file; do ... done < <(find ...)) or redirect with a here-string to keep the loop in the current shell.
agents-suite/automation/instant/configs/instant-execution-config.yaml
Outdated
Show resolved
Hide resolved
| # @ECO-governed | ||
| # @ECO-layer: GL00-09 |
There was a problem hiding this comment.
This file has a .json extension but begins with #-prefixed comment lines, which are not valid JSON. Any JSON parser (including jq, Python's json.loads, etc.) will fail to parse this file. The governance header comments should either be removed, moved to a companion .yaml metadata file, or placed inside the JSON structure as a "_governance" key.
agents-suite/automation/instant/archive/archive-result-20260109-000725.json
Outdated
Show resolved
Hide resolved
agents-suite/automation/instant/archive/metadata-20260109-000725.json
Outdated
Show resolved
Hide resolved
agents-suite/automation/instant/docs/pr-validation-INSTANT-TRIGGERS-IMPLEMENTATION-REPORT.json
Outdated
Show resolved
Hide resolved
agents-suite/automation/instant/scripts/run-instant-execution.sh
Outdated
Show resolved
Hide resolved
agents-suite/automation-platform/src/automation_platform/engines/execution_engine.py
Outdated
Show resolved
Hide resolved
…ig.yaml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…9-000725.json Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…25.json Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…GGERS-IMPLEMENTATION-REPORT.json Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…es/execution_engine.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 90 out of 2753 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # | ||
| # GL Unified Architecture Governance Framework Activated | ||
|
|
||
| #!/usr/bin/env python3 |
There was a problem hiding this comment.
The shebang line #!/usr/bin/env python3 appears on line 9, after several comment header lines. A shebang is only interpreted by the OS when it is the very first line of the file (line 1). As the file currently begins with ECO governance header comments, the shebang is ignored. Move it to line 1 if the script needs to be directly executable.
| # | ||
| # GL Unified Architecture Governance Framework Activated | ||
|
|
||
| #!/usr/bin/env python3 |
There was a problem hiding this comment.
Same issue as in instant_archiver_v1.py: the shebang #!/usr/bin/env python3 is on line 9 instead of line 1. The OS will not interpret it as a shebang, rendering the script non-directly executable. Move it to line 1 if that is the intent.
| This method may mutate ``task.mode`` in place. If the task's mode is | ||
| ``ExecutionMode.STANDARD`` and a command is present, a more specific | ||
| mode is auto-selected and written back to the provided ``Task`` instance | ||
| before execution. | ||
| """ | ||
| if task.mode == ExecutionMode.STANDARD and task.command: | ||
| # Auto-select a more specific mode (intentionally mutates task.mode) | ||
| task.mode = _estimate_mode(task) | ||
|
|
||
| sla = _SLA_CEILINGS[task.mode] | ||
|
|
||
| async with self._semaphore: | ||
| task.mark_running() | ||
| self._status = EngineStatus.RUNNING | ||
|
|
||
| self._events.append( | ||
| TaskDispatched( | ||
| task_id=task.id, | ||
| command=task.command, | ||
| agent_id="engine", | ||
| mode=task.mode.value, | ||
| ) | ||
| ) | ||
|
|
||
| start = time.monotonic() | ||
| try: | ||
| result = await asyncio.wait_for(self._handler(task), timeout=sla) | ||
| elapsed = time.monotonic() - start | ||
| task.mark_completed(result) | ||
| self._tasks_run += 1 | ||
|
|
||
| self._events.append( | ||
| TaskCompleted( | ||
| task_id=task.id, | ||
| success=True, | ||
| duration_seconds=elapsed, | ||
| result=result, | ||
| ) | ||
| ) | ||
| except asyncio.TimeoutError: | ||
| elapsed = time.monotonic() - start | ||
| task.mark_timed_out() | ||
| self._tasks_failed += 1 | ||
| self._events.append( | ||
| TaskCompleted( | ||
| task_id=task.id, | ||
| success=False, | ||
| duration_seconds=elapsed, | ||
| ) | ||
| ) | ||
| raise TaskTimeoutError(task.id, sla) | ||
| except Exception as exc: | ||
| elapsed = time.monotonic() - start | ||
| task.mark_failed(str(exc)) | ||
| self._tasks_failed += 1 | ||
| self._events.append( | ||
| TaskCompleted( | ||
| task_id=task.id, | ||
| success=False, | ||
| duration_seconds=elapsed, | ||
| ) | ||
| ) | ||
| raise |
There was a problem hiding this comment.
execute_task silently mutates the caller's Task object by overwriting task.mode. This is a side-effect that callers are unlikely to anticipate, and the docstring note only partially mitigates this. The method should either work on a copy of the task, or accept an explicit mode parameter, to avoid surprising callers who inspect task.mode after the call and observe an unexpected value.
| This method may mutate ``task.mode`` in place. If the task's mode is | |
| ``ExecutionMode.STANDARD`` and a command is present, a more specific | |
| mode is auto-selected and written back to the provided ``Task`` instance | |
| before execution. | |
| """ | |
| if task.mode == ExecutionMode.STANDARD and task.command: | |
| # Auto-select a more specific mode (intentionally mutates task.mode) | |
| task.mode = _estimate_mode(task) | |
| sla = _SLA_CEILINGS[task.mode] | |
| async with self._semaphore: | |
| task.mark_running() | |
| self._status = EngineStatus.RUNNING | |
| self._events.append( | |
| TaskDispatched( | |
| task_id=task.id, | |
| command=task.command, | |
| agent_id="engine", | |
| mode=task.mode.value, | |
| ) | |
| ) | |
| start = time.monotonic() | |
| try: | |
| result = await asyncio.wait_for(self._handler(task), timeout=sla) | |
| elapsed = time.monotonic() - start | |
| task.mark_completed(result) | |
| self._tasks_run += 1 | |
| self._events.append( | |
| TaskCompleted( | |
| task_id=task.id, | |
| success=True, | |
| duration_seconds=elapsed, | |
| result=result, | |
| ) | |
| ) | |
| except asyncio.TimeoutError: | |
| elapsed = time.monotonic() - start | |
| task.mark_timed_out() | |
| self._tasks_failed += 1 | |
| self._events.append( | |
| TaskCompleted( | |
| task_id=task.id, | |
| success=False, | |
| duration_seconds=elapsed, | |
| ) | |
| ) | |
| raise TaskTimeoutError(task.id, sla) | |
| except Exception as exc: | |
| elapsed = time.monotonic() - start | |
| task.mark_failed(str(exc)) | |
| self._tasks_failed += 1 | |
| self._events.append( | |
| TaskCompleted( | |
| task_id=task.id, | |
| success=False, | |
| duration_seconds=elapsed, | |
| ) | |
| ) | |
| raise | |
| This method temporarily mutates ``task.mode`` during execution. If the | |
| task's mode is ``ExecutionMode.STANDARD`` and a command is present, a | |
| more specific mode is auto-selected and applied to the provided | |
| ``Task`` instance while it is being processed. The original mode is | |
| restored before this method returns. | |
| """ | |
| original_mode = task.mode | |
| selected_mode = original_mode | |
| if original_mode == ExecutionMode.STANDARD and task.command: | |
| # Auto-select a more specific mode (applies during execution only) | |
| selected_mode = _estimate_mode(task) | |
| sla = _SLA_CEILINGS[selected_mode] | |
| async with self._semaphore: | |
| # Ensure that internal execution sees the selected mode, but do not | |
| # leave the caller's Task instance permanently mutated. | |
| if selected_mode is not original_mode: | |
| task.mode = selected_mode | |
| try: | |
| task.mark_running() | |
| self._status = EngineStatus.RUNNING | |
| self._events.append( | |
| TaskDispatched( | |
| task_id=task.id, | |
| command=task.command, | |
| agent_id="engine", | |
| mode=selected_mode.value, | |
| ) | |
| ) | |
| start = time.monotonic() | |
| try: | |
| result = await asyncio.wait_for(self._handler(task), timeout=sla) | |
| elapsed = time.monotonic() - start | |
| task.mark_completed(result) | |
| self._tasks_run += 1 | |
| self._events.append( | |
| TaskCompleted( | |
| task_id=task.id, | |
| success=True, | |
| duration_seconds=elapsed, | |
| result=result, | |
| ) | |
| ) | |
| except asyncio.TimeoutError: | |
| elapsed = time.monotonic() - start | |
| task.mark_timed_out() | |
| self._tasks_failed += 1 | |
| self._events.append( | |
| TaskCompleted( | |
| task_id=task.id, | |
| success=False, | |
| duration_seconds=elapsed, | |
| ) | |
| ) | |
| raise TaskTimeoutError(task.id, sla) | |
| except Exception as exc: | |
| elapsed = time.monotonic() - start | |
| task.mark_failed(str(exc)) | |
| self._tasks_failed += 1 | |
| self._events.append( | |
| TaskCompleted( | |
| task_id=task.id, | |
| success=False, | |
| duration_seconds=elapsed, | |
| ) | |
| ) | |
| raise | |
| finally: | |
| # Restore the original mode so callers do not observe a | |
| # permanently mutated Task.mode after execution. | |
| task.mode = original_mode |
| await self._semaphore.acquire() | ||
| try: | ||
| agent = self._acquire_agent() | ||
| if agent is None: | ||
| # Shouldn't happen with proper semaphore sizing, but be defensive | ||
| self._semaphore.release() | ||
| raise AgentPoolExhaustedError(self._agent_type.value, self._pool_size) |
There was a problem hiding this comment.
When _acquire_agent() returns None on line 100, the semaphore is released manually on line 102 before raising the exception. However, because the acquire() was called outside the inner try block (line 97), and the explicit release() then raises, the outer try/except blocks (lines 146-149) will re-raise the AgentPoolExhaustedError without a second release. This is handled correctly. However, if an exception occurs between line 97 and line 118 (e.g., in agent.assign_task) that is not AgentPoolExhaustedError, the semaphore acquired on line 97 will never be released because the finally block for self._semaphore.release() is inside the inner try (line 141), which would not be reached. To ensure the semaphore is always released, move self._semaphore.release() to a finally block that wraps the entire body after await self._semaphore.acquire().
The repo needed a single, portable bundle containing all existing multi-agent/automation/AI artifacts for downstream migration.
agents-suite/consolidatingbackend/ai,platforms/_shared,platforms/automation-platform,platforms/automation,platforms/eco-superai,platforms/ng-era-platforms, andAgent_Actions.zipto simplify extraction.agents-suite/README.mdoutlines what’s included, source paths, and migration tips (e.g., keep_sharedwithautomation-platformfor protocol imports).Example layout: