- Fix ActivitySource name from 'Microsoft.Agents.AI' to
'Experimental.Microsoft.Agents.AI' matching the Agent Framework default
- Wrap agents with UseOpenTelemetry() via AIAgentBuilder so agent
invocation spans are emitted to the configured OTLP collector
- Add proper disposal of OpenTelemetryAgent wrappers via
SyncDisposableAdapter bridging IDisposable to IAsyncDisposable
- Enable workflow-level telemetry on WorkflowRunner custom graph builds
via WithOpenTelemetry() (HandoffWorkflowBuilder and
GroupChatWorkflowBuilder do not expose this API — framework limitation)
- Fix settings panel help text to be user-facing instead of dev jargon
- Update test assertion for corrected ActivitySource name
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add OTLP export wiring for the sidecar and dev scripts to launch the standalone Aspire Dashboard during development.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The StreamingTextMerger (C#) and mergeStreamingText (TypeScript) contained
custom word-boundary heuristics that inserted spaces between streaming deltas
based on incorrect assumptions. Two bugs caused mid-word spaces:
1. Unconditional space insertion when incoming delta started with uppercase or
digit characters, breaking acronyms (MDA -> M DA, UAG -> UA G)
2. LooksLikeWordBoundary using global token counts that fired on nearly every
mid-word token split (writable -> wr itable, fragile -> frag ile)
Both upstream projects (Copilot SDK and Agent Framework) use simple string
concatenation for delta accumulation. LLM streaming tokens natively include
whitespace when needed, so no boundary detection is required.
Removed all boundary heuristic methods and replaced with plain concatenation.
Kept overlap detection and snapshot handling for event redelivery scenarios.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add turn-stream capability metadata and richer normalized provider events for reasoning blocks, tool lifecycle, and turn boundaries. Track those signals in turn execution state and cover the new Copilot adapter/state behavior with tests.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Extract TryResolveSubWorkflowDefinition that returns null instead of
throwing when a referenced workflow is missing from the library.
Use the tolerant variant in all graph-walking helpers that build
agent indexes, collect agent nodes, and find sub-workflow nodes.
These operations are used for activity UI enrichment and agent
identity resolution — they should degrade gracefully rather than
crash the turn.
The throwing ResolveSubWorkflowDefinition is now only used by
WorkflowRunner.CreateNodeRoute, which is the actual execution
path and correctly fails with a clear error if a reference is
truly missing.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Deep agent resolution in the sidecar now walks sub-workflow nodes so
nested agents carry subworkflowNodeId and subworkflowName on activity
events. New subworkflow-started / subworkflow-completed activity types
let the frontend track sub-workflow lifecycle.
The Activity panel groups nested agents under collapsible sub-workflow
cards with status badges, accent-colored left borders, and smooth
expand/collapse transitions. Cards auto-expand when a sub-workflow
starts running. Workflows without sub-workflow nodes render identically
to before.
Extracted AgentRow, SubWorkflowGroup, and shared accent constants to
a new components/activity/ feature directory. Added
resolveWorkflowAgentHierarchy and buildGroupedActivityRows for
hierarchical activity grouping with dynamic fallback for unresolved
sub-workflow agents.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The CopilotTurnExecutionState was ignoring ToolExecutionStartData.Arguments
when creating tool-calling activity events, despite the Copilot SDK providing
them. This caused the activity panel to show 'Viewed a file' / 'Used rg'
with no contextual details (file paths, search patterns, etc.).
The fix adds NormalizeRawToolArguments to WorkflowRequestInfoInterpreter for
converting the raw object? payload (typically JsonElement) into the normalized
dictionary, then passes ToolExecutionStartData.Arguments through
CreateToolCallingActivity.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAgentBundle.CreateAsync unconditionally resolved the Copilot CLI
path and started a CopilotClient, even for workflows with no agent
nodes (e.g. request-port-only workflows). This caused a hard failure
in CI where the copilot binary is not on PATH.
Move CLI path resolution, client creation, and agent setup inside a
guard that checks whether the workflow actually contains agent nodes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The WorkflowValidator rejected loop edges with an 'always' condition,
but maxIterations already guarantees termination at runtime (enforced by
WorkflowConditionEvaluator). This made built-in templates like
Collaborative Group Chat fail validation immediately.
Relax the check so 'always' conditions are accepted when maxIterations
provides the termination guarantee. The condition error now only fires
when neither a non-default condition nor a maxIterations cap is present.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Previously, CopilotAgentBundle.CreateAsync spawned a separate
CopilotClient (and thus a separate Copilot CLI process) for each
agent in a workflow. When multiple CLI processes started concurrently,
their auto-login mechanisms could race on token refresh, causing
subsequent agents to fail with 'Session was not created with
authentication info or custom provider'.
Share one CopilotClient across all agents in the bundle. Each agent
still gets its own CopilotSession on the shared client. The bundle
owns the client and disposes it after all agents.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add first-class backend support for workflow orchestration modes,
including mode settings, graph scaffolding, mode-aware validation,
and real Agent Framework handoff/group-chat execution paths.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add MVP code-executor and function-executor runtime support, request-port
bridging through Aryx user input, state-scope helpers, lockstep execution
mode handling, and validation/tests for new workflow node kinds.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- parse prompt model and argument-hint metadata and persist model on prompt invocations
- expand markdown-linked file context in scanned prompt and instruction bodies
- discover .claude/rules instructions and support Claude-style paths metadata
- discover customization roots up to the nearest parent repository and watch them for changes
- apply per-turn prompt model overrides before sidecar execution
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move handoff routing and ownership rules out of per-agent system
prompts and into the Agent Framework handoff builder guidance.
This keeps AgentInstructionComposer focused on Aryx-owned system
prompt content while letting WithHandoffInstructions supply the
workflow-level handoff semantics.
- remove handoff-mode runtime guidance from AgentInstructionComposer
- expand HandoffWorkflowGuidance with the triage/specialist rules
- update tests to pin the new split of responsibilities
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Explicitly configure AIAgentHostOptions for the workflow modes that
host agents directly instead of relying on Agent Framework defaults.
- add a shared host-options factory that preserves Aryx's current
behavior
- use custom sequential, concurrent, and round-robin group-chat
builders so all host options are set intentionally
- add workflow-level tests asserting the configured host options
Keep EmitAgentResponseEvents disabled because Aryx still projects
streaming transcript state itself and enabling response events would
require a separate reconciliation change.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Explicitly configure handoff workflows to use
HandoffToolCallFilteringBehavior.HandoffOnly instead of relying on
Agent Framework's current default.
This keeps normal tool-call history visible across handoffs while
still stripping handoff plumbing, and adds a regression test to pin
that behavior.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sub-agent messages bypass the streaming path (turn-delta) entirely due to
SDK batching behavior. They arrive only at turn-complete time via
FinalizeCompletedMessages. Without classification, they appear as separate
chat bubbles cluttering the transcript.
Two-pronged fix:
Sidecar: FinalizeCompletedMessages now tags messages from
_reclassifiedMessageIds with MessageKind='thinking'. This covers messages
that WERE streamed and reclassified during the turn. Added MessageKind
property to ChatMessageDto.
Main process: finalizeTurn detects unstreamed assistant messages (not in
existing session.messages) and classifies them as thinking when a visible
response was already streamed. Emits message-reclassified events so the
renderer can update incrementally, though the primary path is the
workspace:updated broadcast which already includes the correct messageKind.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When the pre-tool-use hook returns 'ask', the Copilot CLI creates
PermissionRequestHook instead of categorized PermissionRequestRead/
Write/Shell. This caused 'Permission: hook' labels and broke category-
based auto-approval ('Always approve read' wouldn't cover grep/glob).
Add ResolveHookToolCategory mapping in CopilotApprovalCoordinator to
map known tool names (view/grep/glob→read, edit/create→write, etc.)
to their permission categories. Wire into GetFallbackToolName,
BuildPermissionApprovalEvent, and CreateApprovalPolicyOutput so:
- Approval banner shows 'Permission: read' instead of 'Permission: hook'
- 'Always approve' stores the category key, covering all tools in it
- Hook short-circuits when category is already auto-approved
Unknown tools (MCP, custom) keep existing 'hook' behavior.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Allow SDK-managed orchestration tools to bypass pre-tool approval prompts so Aryx matches Copilot CLI behavior for non-side-effectful meta tools.
Keep store_memory under the existing memory approval category.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>