{"record":{"id":"ee074bc3c64d4072","repo":"bytedance/deer-flow","slug":"agent-name-is-required-to-upsert-a-fact","errorCode":null,"errorMessage":"agent_name is required to upsert a fact","messagePattern":"agent_name is required to upsert a fact","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/storage.py","lineNumber":1323,"sourceCode":"            \"complete\": False,\n            \"version\": memory_file.get(\"version\", DOCUMENT_VERSION),\n            \"revision\": memory_file.get(\"revision\", 0),\n            \"lastUpdated\": memory_file.get(\"lastUpdated\", \"\"),\n            \"upsertedFacts\": [copy.deepcopy(value) for action, value, _ in notifications if action == \"upsert\" and isinstance(value, dict)],\n            \"deletedFactIds\": [str(value) for action, value, _ in notifications if action == \"remove\"],\n        }\n\n    def upsert_fact(\n        self,\n        fact: dict[str, Any],\n        *,\n        user_id: str | None = None,\n        agent_name: str | None = None,\n        expected_manifest_revision: int | None = None,\n        expected_fact_revision: int | None = None,\n    ) -> dict[str, Any]:\n        if agent_name is None:\n            raise ValueError(\"agent_name is required to upsert a fact\")\n        incoming = copy.deepcopy(fact)\n        incoming[\"id\"] = str(incoming.get(\"id\") or f\"fact_{uuid.uuid4().hex}\")\n        fact_id = incoming[\"id\"]\n        return self.apply_changes(\n            {\"upserts\": [incoming], \"upsertRevisions\": {fact_id: expected_fact_revision}},\n            user_id=user_id,\n            agent_name=agent_name,\n            expected_manifest_revision=expected_manifest_revision,\n            allow_manifest_rebase=True,\n        )\n\n    def delete_fact(\n        self,\n        fact_id: str,\n        *,\n        user_id: str | None = None,\n        agent_name: str | None = None,\n        expected_manifest_revision: int | None = None,","sourceCodeStart":1305,"sourceCodeEnd":1341,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/storage.py#L1305-L1341","documentation":"MemoryStorage.upsert_fact() requires agent_name because it delegates to apply_changes, which writes to the agent-scoped fact file. The guard fires before the fact is deep-copied or an id is generated, so a failed call has no side effects and no id is consumed.","triggerScenarios":"storage.upsert_fact({'content': ...}) with agent_name omitted - typically a generic 'save fact' service method that only received the fact payload.","commonSituations":"A memory-extraction step running outside an agent context; refactor that lost the agent identity; defaulting agent_name=None in a wrapper signature and never overriding it.","solutions":["Thread the agent identity through: storage.upsert_fact(fact, agent_name=agent_name, user_id=user_id).","If upserting outside any agent is a real use case, route it to your own scoped 'default' agent name rather than None.","Make agent_name a required positional/keyword in your wrapper so it cannot be silently dropped."],"exampleFix":"# before\ndef remember(fact: dict):\n    storage.upsert_fact(fact, user_id=user_id)\n\n# after\ndef remember(fact: dict, *, agent_name: str):\n    storage.upsert_fact(fact, agent_name=agent_name, user_id=user_id)","handlingStrategy":"validation","validationCode":"if agent_name is None:\n    raise HTTPException(400, \"agent_name required\")\nstorage.upsert_fact(fact, agent_name=agent_name, user_id=user_id)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Make agent_name required (no default) in wrapper signatures.","Bind memory writes to the active agent context object rather than passing scopes manually.","Default to a named sentinel agent instead of None when no agent context exists."],"tags":["memory","scoping","validation","deermem"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}