Tinderbox Forum

A beginner fumbles with agents and note hierarchy

Hi–I’m in a muddle about several things, mostly agents and getting info within a note’s hierarchy. I’ve read the TBX documentation wiki and “The Tinderbox Way” as carefully as possible and experimented with so many things–parent, this, that, $Text, $Name, and various syntax possibilities–apparently, ‘parent.$Text.contains(“foo”)’ doesn’t work.

Here’s my situation. I’m doing a second draft on an article about the Beatles, especially their 3 months in Hamburg. I’ve mentally cut the first draft into strips of text and summarized each text unit as a single note.

For example, the note about their terrible lodgings in Hamburg has $Name set to “05 Hamb living conditions”. This note’s $Text is “adversity, determination, overcoming”–which are three topics that this note belongs to. And all these notes are inside the container/note “Beatles M2 WC *5/15”.

Here’s what I’d like to do. I’d like to create an agent–one that is in the same window/container as the notes themselves–that finds every note that contains the text “adversity” in its $Text field.

Here’s one of the many queries I’ve tried to accomplish this:


inside("Beatles M2 WC *5/15") & $Text.contains("adversity")

Q1: This doesn’t work. What should this be instead?

So, I’m going to be doing this several times, and it’s irritating to need to go into the code–whatever code it is that works–and change the text to be matched. Ideally, I would like to create an agent called, for example, “adversity”, and have the aliases of the desired notes inside it–i.e., the same results as the situation I described above. So:

Q2: How should the query code of Q1 be changed to do this?

Getting an agent to do what I’ve described is key to being productive with this “Beatles” container/note (which is within a much bigger TBX file)–and with other TBX documents I will write in the future.

Help me, Obi-Wan Kenobi, you’re my only hope.

Have you tested an agent that is solely the first term?

inside("Beatles M2 WC *5/15")

I suspect (without validation) that there’s something about the * and/or the / in the container name that causes a fail. So try to rename the container without these characters and see if there’s a result.

OTOH, for what it’s worth, a small test file I created works exactly as you expected it to work. But I am using probably a later version of Tinderbox than you have since I’m using the backstage beta version. So see if this test works for you – if not, it might be because something has been fixed but not yet released. Just a thought.

Test Example.tbx (88.3 KB)

A general principle: when working out a complex Tinderbox issue it is often best to test in a smaller file with the least amount of noise and build up the testing from the smallest action or agent logic to the more complex. That often results in useful information.

Finally, if you want to post a sample file here that fails but also doesn’t disclose your private info, that would be helpful for others to diagnose.

Re the slash in name/path, if you want to use action code (also used to write agent queries) then avoid forward slash /, parentheses () and semicolon ; characters in note names as these are currently problematic for action code parsing (under the hood - so beyond the users reach to alter).

The issue points up an avoidable constraint that likely creeps in when moving form paper systems, that of over-loading the note title ($Name) with admixed strands of metadata. My suspicion is that in "Beatles M2 WC *5/15" sub-string ‘M2’, ‘WC’ and ‘*5/15’ all have discrete meanings. If so, whether or not you include them in the note’s title (given the issue with troublesome characters) do give thought to capturing these strands in their own attributes as well/instead of in the name. It makes querying (i.e. fine addressability) a lot better.

The first step in the latter process is seen in using $Tags to store the data. But that merely shifts the discrete strands to a a tag-soup. Real leverage comes from de-interleaving the strands into discrete user attributes, e.g locations vs temporal events. An upside of this work is once teased out it is possible to use different data types for different metadata strands. For instance, time-based metadata may well help more when be stored as dates, allowing date-arithmetic calculations. For strands with a fixed set of possible values, suggested values can help save on re-keying in per-note values. And so on…

Anyway, this is just observation about leveraging your work and certainly not criticism. :slight_smile:

One more thought, if you are in the current bind of having a lots of existing notes with ‘problematic’ characters (as described in my previous post), there is one workaround. Not everyone will like it, but I offer it for what it is worth. In short, ‘clean’ the note titles of ‘bad’ characters, saving the original $Name in a user String attribute. The latter can be used as a display string, whilst now having ‘safe’ $Name values. If new to action code and trying this, take an explicit copy of your document before starting, indeed, try first in a small test document so you have confidence applying en masse to real data of value. The point of doing this is you likely won’t then mess up and need to roll back, but if you do it is easy, plus you feel more confident. If that seems like ‘extra work’, it’s a lot easier than blundering forward and having to roll back unintended mistaken changes.

Let’s assume the notes affected all use on prototype—you likely don’t want or need to change every not. We’ll assume here they are using prototype ‘pNote’ (using prototypes efficiently is a big ease-of-use boost). We’ll make a user String-type attribute $TrueName. Now, in an agent set to query for $prototype=="pNote" the agent action is:

$TrueName = $Name
$DisplayExpression = $TrueName
$Name = $Name.replace("/","_").replace("\(","[").replace("\)","]");

First we safely store the current $Name in $TrueName. We then use the latter as a display expression, so the $Name on screens looks as you expect. Next in $Name we replace all slashes with underscores and all parentheses with square brackets.

Separately, consider going go to the prototype(s) processed above and add $TrueName to the prototype’s Key Attributes, so you can see the changes if confused. The view pane will be showing $TrueName for the notes, but when selected, the title in the text pane with show $Name. $Name is what you will need in your queries.

Now for the original note “Beatles M2 WC *5/15”, the latter will be $TrueName but $Name is now the ‘safer’ “Beatles M2 WC *5_15” and you query becomes:

("Beatles M2 WC *5_15") & $Text.contains("adversity")

This approach is not everyone’s style, but I offer it as a work-around for the current limitations of using characters like slashes in their $Name.

FWIW, I developed this after I’d made a large TBX where the note names were title of scientific papers—which use a more eclectic range of characters than one wound suppose, and certainly the problematic ones discussed. The above allowed me to proceed with analytical work with relevant ease having memorised the small number of mapped characters, e.g. /_, etc.

Use the technique if it helps, but as ever in Tinderbox there is more than one way and use whatever suits you. :slight_smile:

Stepping back: the most useful approach to coping with agent confusions is to simplify until the agent cannot conceivably fail. Then, one of two things can happen.

  • It works! You’re happy. And now you can add just a little more complexity — so little that failure is inconceivable —and test that. Before you know it, you’re done.

  • It doesn’t work. “Inconceivable!” you shout in frustration. Perhaps you go off and watch The Princess Bride, or get a snack. Coffee at least. Now, it might be that you’ll see the problem: curly quotes where you need straight quotes, or a typo. So you fix that, and all is well. Or, perhaps there’s something even simpler: try that. If it still doesn’t work, go ahead and ask here.

I am well aware that when one asks a “How do I …?” question, it can be frustrating to get an answer whose premise is: Maybe you could try things a different way.

With that stated: My experience is that it might work more easily if, rather than having “adversity, determination, overcoming” in the $Text of a note, instead you create an attribute called something like $Qualities (or whatever), and have “adversity,” “determination”, etc by values that you enter in that space.

The long version of how this could be handy is in this thread from a couple of years ago, called “How to Use the Attribute Browser.” I have a functionality / goal similar to what I think you are trying to attain, and I have found the Attrib Browser to be 90% of the time the easiest and most elegant way to get there. Check it out! (Also, it means you don’t have to worry about issues of hierarchy and containers at all – unless you want to, to limit to scope of a query.)

2 Likes