Context
Found while addressing review feedback on #683. Splitting it out rather than widening that PR, for a reason given below.
#683 established the contract that a node which answers a question carries that question's metadata onto the Answer it emits, so an evaluator downstream can still find the reference it should be scored against. It applied that at two sites:
packages/ai/src/ai/common/llm_base.py:98,103
packages/ai/src/ai/common/chat.py:719,740
Problem
packages/ai/src/ai/common/agent/agent.py — the emit_answers_lane block in run_agent, around :233 — builds its Answer and writes it without merging question.metadata:
answer = Answer(expectJson=False)
answer.setAnswer(answer_payload.get('content', ''))
iInstance.instance.writeAnswers(answer)
question is in scope (it is a required keyword argument of run_agent, :92).
This is one shared site covering all six agent nodes:
agent_crewai/crewai_agent, agent_crewai/crewai_manager
agent_deepagent/deepagent_agent
agent_langchain
agent_llamaindex
agent_rocketride
Impact
eval_cobalt cannot score an agent's output. "Evaluate my agent" is an obvious use of the evaluation nodes added in #683, and today it silently produces cobalt_score: 0.0 — the same failure mode #683 fixed for the prompt node, at a different hop.
Fix
One line, plus one import:
# packages/ai/src/ai/common/agent/agent.py:25
from ai.common.utils import merge_metadata, safe_str
# in run_agent, before writeAnswers
merge_metadata(answer, getattr(question, 'metadata', None))
Why this was not done in #683
It needs a test that carries a reference across the agent hop, and that is not cheap to write honestly. AgentBase.run_agent pulls in AgentHostServices and ToolDescriptor from rocketlib and performs tool discovery, so an offline test means rebuilding a good chunk of the engine surface from stubs.
@asclearuc's blocking note on #683 was that all 175 tests exercised each node in isolation behind mocks, and that this is precisely why the metadata bug shipped green for four review rounds. Adding a second untested cross-node metadata fix in the same PR would have repeated that mistake. This deserves a test built on something more real than a stub tower.
Out of scope for this issue
Other terminal nodes also emit Answers without metadata, but they synthesize an answer from query results rather than answering the question, so each needs its own judgement call:
packages/ai/src/ai/common/database/db_instance_base.py:652 (postgres/mysql/clickhouse)
packages/ai/src/ai/common/graph/graph_instance_base.py:498,537, nodes/src/nodes/graph_arango/IInstance.py:243
nodes/src/nodes/rerank_cohere/IInstance.py:128-131 (also terminates the questions lane entirely)
nodes/src/nodes/search_exa/exa_search.py:114-115 (forwards the question correctly; only its Answer lacks metadata)
- vector-store answers lane,
packages/ai/src/ai/common/store/document_store.py:373 (questions lane forwards correctly, so RAG → LLM → eval works today)
Refs #683, #1747
Context
Found while addressing review feedback on #683. Splitting it out rather than widening that PR, for a reason given below.
#683 established the contract that a node which answers a question carries that question's
metadataonto theAnswerit emits, so an evaluator downstream can still find the reference it should be scored against. It applied that at two sites:packages/ai/src/ai/common/llm_base.py:98,103packages/ai/src/ai/common/chat.py:719,740Problem
packages/ai/src/ai/common/agent/agent.py— theemit_answers_laneblock inrun_agent, around:233— builds itsAnswerand writes it without mergingquestion.metadata:questionis in scope (it is a required keyword argument ofrun_agent,:92).This is one shared site covering all six agent nodes:
agent_crewai/crewai_agent,agent_crewai/crewai_manageragent_deepagent/deepagent_agentagent_langchainagent_llamaindexagent_rocketrideImpact
eval_cobaltcannot score an agent's output. "Evaluate my agent" is an obvious use of the evaluation nodes added in #683, and today it silently producescobalt_score: 0.0— the same failure mode #683 fixed for thepromptnode, at a different hop.Fix
One line, plus one import:
Why this was not done in #683
It needs a test that carries a reference across the agent hop, and that is not cheap to write honestly.
AgentBase.run_agentpulls inAgentHostServicesandToolDescriptorfromrocketliband performs tool discovery, so an offline test means rebuilding a good chunk of the engine surface from stubs.@asclearuc's blocking note on #683 was that all 175 tests exercised each node in isolation behind mocks, and that this is precisely why the metadata bug shipped green for four review rounds. Adding a second untested cross-node metadata fix in the same PR would have repeated that mistake. This deserves a test built on something more real than a stub tower.
Out of scope for this issue
Other terminal nodes also emit Answers without metadata, but they synthesize an answer from query results rather than answering the question, so each needs its own judgement call:
packages/ai/src/ai/common/database/db_instance_base.py:652(postgres/mysql/clickhouse)packages/ai/src/ai/common/graph/graph_instance_base.py:498,537,nodes/src/nodes/graph_arango/IInstance.py:243nodes/src/nodes/rerank_cohere/IInstance.py:128-131(also terminates the questions lane entirely)nodes/src/nodes/search_exa/exa_search.py:114-115(forwards the question correctly; only its Answer lacks metadata)packages/ai/src/ai/common/store/document_store.py:373(questions lane forwards correctly, so RAG → LLM → eval works today)Refs #683, #1747