Tools fail. A feed stops, an upstream source goes down, a request asks for a ticker that is not covered. None of that is unusual. What matters is what the tool sends back, because an agent will turn whatever it receives into a confident sentence.
Why an empty answer is dangerous
Picture a tool that returns an empty list when its feed has stopped. A person looking at a blank screen would suspect a fault. A model does not. It reads the empty list as data and reports that nothing is trending, nothing is moving, no filings were made. That is a statement about the market, and it is false. The full argument is in an empty array is a claim about the world.
What a good error carries
A good error has three parts. It says plainly that the request failed. It says why, in a form a program can read. And where waiting would help, it says when to try again. NoVo’s server follows this rule. A stopped feed answers with an error and a retry time. It never answers with an empty result.
The tools carry this in specific ways. If the watch behind get_robinhood_trending has stopped, the tool returns an error, never an empty list. If the public calendar behind get_earnings_dates fails, the error names the upstream. If you ask get_short_volume for a ticker it does not carry, it refuses by name and lists what it covers. It does not hand back another instrument’s number.
Not yet is a third answer
Some states are neither data nor failure. Before a session’s first pass, get_gamma_profile answers that nothing is banked yet. That is different from saying gamma was flat. In get_ticker_brief, a section that cannot answer is marked as not carried, with a reason. An agent should repeat these as they are. Nothing banked yet is a complete and honest answer.
What the agent should do
First, say it. The tool is down, or the ticker is not covered, or the reading needs a paid plan. Second, pass on the retry time if one came back. Third, offer what it can still read from a tool that did answer. That is the whole job.
What it must not do
It must not fill the gap from memory. This is the most common failure, and it is hard to spot because the answer still reads well. It must not retry in a tight loop either. A retry time is an instruction, and hammering a stopped feed helps nobody. And it must not quietly swap in a different ticker or a different tool and present the result as what you asked for.
Putting it in the instructions
One line covers it: if a tool returns an error or a refusal, tell me what it said and do not answer that part from memory. The design of the errors themselves is covered in an error message is not an interface. The tools and their failure behavior are documented on the MCP & API page.