Skip to content

[BUG] [v0.0.7] app-server /agents API writes to .factory/agents, so standard loaders never discover created agents #53528

Open
CortexLM/cortex-code
#335

Description

@DDDDDGCSM

Project

cortex

Description

The app-server custom agent API uses a different storage layout from the rest of Cortex:

  • POST /api/v1/agents with scope=project writes to .factory/agents
  • POST /api/v1/agents with scope=user writes to ~/.factory/agents

But the standard agent loaders and UIs do not scan .factory/agents at all. They scan:

  • .agents
  • .agent
  • .cortex/agents
  • ~/.cortex/agents
  • ~/.config/cortex/agents

So an agent created through the app-server API can be written successfully but still remain invisible to the standard loader used by the rest of Cortex.

Error Message

No explicit error is shown. The bug is a silent storage mismatch: create succeeds, but discovery never finds the created agent.

Debug Logs

CARGO_HOME=/tmp/cargo-home-rsproxy cargo test -p cortex-app-server project_agent_created_via_api_is_not_discoverable_by_standard_loader --manifest-path /tmp/cortex-upstream/Cargo.toml -- --test-threads=1 --nocapture

running 1 test
factory_path=/tmp/.../.factory/agents/factory-only-agent.md
loader_paths=[project/.agents, project/.agent, project/.cortex/agents, HOME/.cortex/agents, XDG_CONFIG_HOME/cortex/agents]
loaded_names=[]
ok

System Information

macOS Darwin 25.x (Apple Silicon)
Cortex v0.0.7 source checkout
Rust toolchain: cargo 1.95.0 / rustc 1.95.0

Screenshots

Cortex app-server agent path mismatch evidence

Steps to Reproduce

  1. Use the app-server custom agent creation path with scope=project.
  2. Observe the created file is written under .factory/agents/<name>.md.
  3. Run the standard custom agent loader for the same project root.
  4. Observe that the loader only scans .agents, .agent, .cortex/agents, ~/.cortex/agents, and ~/.config/cortex/agents.
  5. The agent that was just created by the API is not discovered.

The targeted proof command above demonstrates the mismatch directly and prints both:

  • the path where the app-server wrote the new agent
  • the exact directories searched by the standard loader

Expected Behavior

Agents created via the app-server API should be stored in a directory that the standard Cortex agent loaders also scan, so the created agent becomes discoverable and usable immediately across the rest of the product.

Actual Behavior

The API writes custom agents to .factory/agents / ~/.factory/agents, but the standard loaders never scan those directories. The created agent exists on disk but is effectively invisible to the rest of Cortex.

Additional Context

Relevant code paths:

  • src/cortex-app-server/src/api/agents.rs
    • project agents: .factory/agents
    • user agents: ~/.factory/agents
  • src/cortex-agents/src/custom/loader.rs
    • scans .agents, .agent, .cortex/agents, ~/.cortex/agents, ~/.config/cortex/agents
  • src/cortex-tui/src/interactive/builders/agents.rs
    • uses .cortex/agents and ~/.config/cortex/agents
  • src/cortex-commands/src/builtin/agents_cmd.rs
    • documents .cortex/agents/ and ~/.config/cortex/agents/

This is not just a path-style inconsistency. It creates a functional mismatch where app-server-created agents are not discoverable by the standard loader and therefore do not participate in the normal custom-agent flow.

Activity

  1. atlas-cortex commented on May 12, 2026

    @atlas-cortex

    ✅ Validation Summary — Issue #53528

    All validation checks passed. 1/17 code rules failed | 1 PENALIZE | 14 LLM instructions active

    Confidence Score: 4/5

    • All validation checks passed. This submission meets the bounty requirements.

    Validation Checks

    Check Status Detail
    Media Evidence ✅ Pass Evidence found and accessible
    Spam Detection ✅ Pass Score: 21% — no spam signals
    Duplicate Detection ✅ Pass No significant overlap with existing issues
    Code Verification ✅ Pass Bug confirmed in source code (confidence: 100%) — The code confirms the bug report. The app-server API writes custom agents to `.f
    Edit History ✅ Pass No suspicious edits
    LLM Evaluation ✅ Pass All validation checks passed. 1/17 code rules failed

    Validation Pipeline

    %%{init: {'theme': 'neutral'}}%%
    flowchart TD
        A["Issue #53528"] --> B{"Media Check"}
        B -->|"✅ Found"| C{"Spam Check"}
        C -->|"✅ Clean"| D{"Duplicate Check"}
        D -->|"✅ Unique"| CV{"Code Verify"}
        CV -->|"✅ Confirmed"| E{"Edit History"}
        E -->|"✅ Normal"| F{"LLM Evaluation"}
        F -->|"✅ Valid"| G["✅ Approved"]
        style G fill:#51cf66,color:#fff
    
    Loading

    Raw Evidence

    {
      "media": {
        "hasMedia": true,
        "accessible": true,
        "urls": [
          "https://raw.githubusercontent.com/DDDDDGCSM/solid-carnival/master/evidence/cortex-agents-path-mismatch-evidence.png"
        ],
        "evidence": [
          "Found 1 media URL(s) via GitHub rendered HTML",
          "1 URL(s) accessible"
        ]
      },
      "spam": {
        "overallScore": 0.20683520599250937,
        "details": "template=0.33 (1 recent issues compared); burst=0.25 (2 issues in 2h window); parity=0.00; overall=0.21 (threshold=0.7)"
      },
      "duplicate": {
        "isDuplicate": false,
        "similarity": 0.5648345888398014,
        "topSimilar": [
          {
            "issueNumber": 51577,
            "title": "cortex agent list/show ignore CORTEX_HOME — always scan ~/.cortex/agents",
            "similarity": 0.5648345888398014
          },
          {
            "issueNumber": 52221,
            "title": "[BUG] [v0.0.7] cortex agent create --non-interactive ignores CORTEX_HOME and writes to the default personal agents directory",
            "similarity": 0.5534158950292818
          },
          {
            "issueNumber": 51989,
            "title": "[BUG] [v0.0.7] cortex agent list/show ignore personal agents stored in the active CORTEX_HOME profile",
            "similarity": 0.5482197872066024
          },
          {
            "issueNumber": 52779,
            "title": "[BUG] [v0.0.7] `cortex acp --agent` validates via `dirs::home_dir().join(\".cortex\")` instead of `get_cortex_home()`",
            "similarity": 0.5354052975933891
          },
          {
            "issueNumber": 52261,
            "title": "[BUG] [v0.0.7] cortex agent copy ignores CORTEX_HOME and writes the copied agent to the default personal agents directory",
            "similarity": 0.5313866741345479
          }
        ]
      },
      "editHistory": {
        "fraudScore": 0,
        "editCount": 0,
        "details": "No edits detected"
      },
      "codeVerification": {
        "plausible": true,
        "confidence": 1,
        "reasoning": "The code confirms the bug report. The app-server API writes custom agents to `.factory/agents` and `~/.factory/agents`, but the standard custom agent loader in `cortex-agents` does not include these directories in its search paths. This results in agents created via the API being invisible to the rest of Cortex.",
        "codeEvidence": "src/cortex-app-server/src/api/agents.rs uses `.factory/agents` and `~/.factory/agents` for creating and listing agents. However, src/cortex-agents/src/custom/loader.rs uses `.agents`, `.agent`, `.cortex/agents`, `~/.cortex/agents`, and `~/.config/cortex/agents` in `with_default_paths`.",
        "screenshotValid": true,
        "screenshotReasoning": "The screenshot shows the test output demonstrating the mismatch between the factory path and the loader paths."
      },
      "rules": {
        "codeResults": {
          "passed": [
            {
              "ruleId": "content.no-profanity",
              "category": "content",
              "severity": "flag",
              "passed": true,
              "message": "Issue should not contain excessive profanity or abusive language",
              "weight": 1
            },
            {
              "ruleId": "content.reasonable-length",
              "category": "content",
              "severity": "flag",
              "passed": true,
              "message": "Issue body should not exceed 15000 characters (possible spam dump)",
              "weight": 1
            },
            {
              "ruleId": "content.has-context",
              "category": "content",
              "severity": "penalize",
              "passed": true,
              "message": "Issue should mention the affected page, component, or URL",
              "weight": 0.2
            },
            {
              "ruleId": "media.require-evidence",
              "category": "media",
              "severity": "require",
              "passed": true,
              "message": "Issue must include at least one screenshot or video URL",
              "weight": 1
            },
            {
              "ruleId": "media.must-be-accessible",
              "category": "media",
              "severity": "require",
              "passed": true,
              "message": "All media URLs must be publicly accessible (HTTP 200)",
              "weight": 1
            },
            {
              "ruleId": "media.no-placeholder-urls",
              "category": "media",
              "severity": "reject",
              "passed": true,
              "message": "Media URLs should not be placeholder or example URLs",
              "weight": 1
            },
            {
              "ruleId": "scoring.suspicious-edits",
              "category": "scoring",
              "severity": "penalize",
              "passed": true,
              "message": "Penalize issues with concerning edit history (fraud score > 0.3)",
              "weight": 0.25
            },
            {
              "ruleId": "spam.high-score-reject",
              "category": "spam",
              "severity": "reject",
              "passed": true,
              "message": "Reject issues with spam score above 0.85",
              "weight": 1
            },
            {
              "ruleId": "spam.generic-title",
              "category": "spam",
              "severity": "penalize",
              "passed": true,
              "message": "Title should not be a generic/template title",
              "weight": 0.4
            },
            {
              "ruleId": "spam.body-is-title-repeat",
              "category": "spam",
              "severity": "penalize",
              "passed": true,
              "message": "Body should not be a simple repetition of the title",
              "weight": 0.5
            },
            {
              "ruleId": "spam.no-ai-filler",
              "category": "spam",
              "severity": "flag",
              "passed": true,
              "message": "Body should not contain obvious AI-generated filler phrases",
              "weight": 1
            },
            {
              "ruleId": "validity.min-body-length",
              "category": "validity",
              "severity": "reject",
              "passed": true,
              "message": "Issue body must be at least 50 characters",
              "weight": 1
            },
            {
              "ruleId": "validity.min-title-length",
              "category": "validity",
              "severity": "reject",
              "passed": true,
              "message": "Issue title must be at least 10 characters",
              "weight": 1
            },
            {
              "ruleId": "validity.no-empty-body",
              "category": "validity",
              "severity": "reject",
              "passed": true,
              "message": "Issue body must not be empty or only whitespace",
              "weight": 1
            },
            {
              "ruleId": "validity.has-steps-or-description",
              "category": "validity",
              "severity": "penalize",
              "passed": true,
              "message": "Issue body should contain structured content (steps, expected/actual behavior)",
              "weight": 0.3
            },
            {
              "ruleId": "validity.not-a-feature-request",
              "category": "validity",
              "severity": "flag",
              "passed": true,
              "message": "Issue should describe a bug, not a feature request",
              "weight": 1
            }
          ],
          "failed": [
            {
              "ruleId": "scoring.duplicate-threshold",
              "category": "scoring",
              "severity": "penalize",
              "passed": false,
              "message": "Issue has moderate similarity to existing issues, suggesting partial overlap.",
              "weight": 0.3
            }
          ]
        },
        "llmInstructions": [
          "Always prioritize concrete evidence (screenshots, videos, URLs) over the quality of the written description. A poorly written report with clear visual proof of a bug is VALID. A beautifully written report with no evidence is INVALID.",
          "A valid bug report must contain enough information for an engineer to reproduce the issue. If the steps to reproduce are missing or impossibly vague (\"it just broke\"), the issue is INVALID.",
          "You MUST call the deliver_verdict function exactly once. Do not output a JSON object manually. Do not output your verdict in plain text. Use the tool.",
          "Be highly suspicious of submissions that follow a rigid template: same structure, same phrasing, with only the page name or URL swapped. These are template-farmed and should be INVALID. Look for: identical sentence structure, placeholder-like descriptions, formulaic \"Steps to Reproduce\".",
          "When similar issues exist, the OLDER issue (lower issue number) always takes precedence. The newer submission is the duplicate, never the other way around.",
          "Confidence scores must be calibrated: use 0.9+ only when evidence is unambiguous and complete. Use 0.5-0.7 when the issue is borderline. Use below 0.5 when you are genuinely uncertain. Never default to 0.5 — commit to a direction.",
          "Do not give the benefit of the doubt. Missing evidence means INVALID. Unclear reproduction steps means INVALID. Inaccessible media means INVALID. The burden of proof is on the submitter.",
          "In the reasoning field, explain your step-by-step analysis BEFORE stating your conclusion. Cover: evidence quality, clarity, spam signals, and duplicate overlap in that order.",
          "Never mention internal scoring thresholds, rule IDs, detection heuristics, or system architecture in the recap field. The recap is public-facing. Keep reasoning technical but recap user-friendly.",
          "If the issue body reads like AI-generated boilerplate (phrases like \"It is important to note\", \"Furthermore\", \"In conclusion\", excessive politeness, no specific technical details), treat it as strong evidence of spam. AI-generated issues with no real bug details are INVALID.",
          "If the pre-computed media check says media URLs exist, verify the description matches what a screenshot would show. If the description talks about a login page but the context suggests the screenshot is of something unrelated, flag this as suspicious.",
          "Never soften a verdict out of sympathy. \"I can see you tried hard but...\" is not acceptable. If the submission does not meet criteria, it is INVALID regardless of apparent effort.",
          "Write your reasoning and recap in a professional, neutral tone. Do not be sarcastic, condescending, or emotional. State facts.",
          "The recap field must be 2-3 sentences maximum. It will be posted as a public comment. No bullet points in recap — use flowing prose."
        ],
        "totalCodeRules": 17,
        "totalLLMRules": 14,
        "hasReject": false,
        "hasFailed": true,
        "penaltyScore": 0.3,
        "summary": "1/17 code rules failed | 1 PENALIZE | 14 LLM instructions active"
      }
    }

    Validated by Atlas • 2026-05-12

  2. Bortlesboat commented on May 12, 2026

    @Bortlesboat

    Opened upstream PR: CortexLM/cortex#269

    The fix moves the app-server /agents storage and lookup paths from .factory/agents to the standard Cortex agent directories used by the loaders: project agents in .cortex/agents and global agents in the OS config-dir cortex/agents path. It also adds regression coverage for project agent creation/listing through the app-server API.

    Verification run:

    • cargo test -p cortex-app-server project_agent -- --nocapture
    • cargo test -p cortex-app-server api::agents -- --nocapture
    • cargo test -p cortex-app-server --lib -- --skip tools::shell::tests::test_execute_shell
    • cargo check -p cortex-app-server
    • cargo fmt --check --package cortex-app-server
    • git diff --check
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    ideIssues related to IDEvalidValid issue

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions