In a simple test document, I create a note “container” and then add a child “child”.
A simple agent has a query that returns the children of “container”.
If I rename “container” to “renamed container”, the agent still behaves correctly, updating even when I add “sibling” and “third child” to “renamed container”.
But the agent query still refers to the target note as “container”.
I’m glad I can’t carelessly break my agents, but I’m finding it a little hard to trace what older agents are querying.
How resilient is this behavior? Is there any way to tell which agents are querying obsolete names? Is there any way to update them?
The behaviour you describe is … unexpected. If you change the query or the query’s target such that they no longer match the query, then the agent (when next updating†) should find differing results.
But unfortunately we’re lacking the most important bit of info: the query (or even better a small TBX exhibiting the behaviour. Having the query is key to answering the questions. Without it we’ve no idea how the agent is finding/matching notes, given that there a multiple ways to do the query. I don’t note this to nit-pick but simply to get a proper understanding of the test case.
For instance, I can’t replicate your scenario using the above info, suggesting the exact query used is likely part of the mix. Also unclear is if agents are querying the results of other agents. If so, a change in the underlying queried info can take a few cycles to update.
For example: if agent A looks at agent B which looks at agent C then a full ‘flush’ of info would take 3 cycles: c updates, B notices C 's results have changed and updates, A notices B’s results have changed and updates.
If you are seeing the effect you describe in a large TBX document, e.g. your main working TBX, I’d suggest replicating the effect in the smallest possible file. If the issue doesn’t occur in the latter, more complex interplay effects may be at work in your larger TBX. By then scaling out the scenario in the small test TBX you may be able to spot the cause of the issue.
Aside: I’d also be very cautious doing supposedly definitive tests using note/agent/container names that are also designators as this can lead to unassumed (by the user) results. For instance, a simple fix to your scenario is to call your original the child ‘A child’ as child is a specific action code designator. Doing this avoids false positives or negatives whose exact can otherwise be hard to spot.
†. Agents update, in a small doc, quite often. If unsure, use File ▸ Update Agents Now too force all agents to re-run their query.
So all works as expected. Did you perhaps turn your agent off (so it wasn’t updating)? If the latter the existing aliases remain (as the query is not run).
I get the impression this is an “unintended feature” arising from the way Tinderbox agents are optimized under the hood, and it’s not something we should rely on.
So to the original question: Is there any way to track down any agents that might be trying to query against containers that don’t exist?
If we are looking for notes that are inside(doesNotExist), then we will find no notes. If there are not too many agents, manually examining each agent that finds no notes might be an easy solution.
If we know that the agents of interest use inside(), we could write an agent that looks for the pattern $AgentQuery.contains("inside"), and could even extract the argument to inside. That gives you a list of note names or paths to confirm.
If you want to programmatically test whether a path $MyString exists, see whether $IDString($MyString) is empty or not. Only non-existent notes will have no $IDString.
I believe that the most general case is undecidable. If we have a function pick() which does some calculation and return a path, then we may not be able to say whether inside( pick() ) exists or not. But that’s unlikely to be your headache.
Tinderbox is sometimes slow to remove notes from agents if the note formerly satisfied the query, but no longer does.
If you have a container you expect to rename, and want to refer to that container in an agent, you could refer to that container by its $IDString. Or, you could link to that container (perhaps with a special link type) and then use eachLink(){} to get the path to the destination.