My take on this:
First, I would *not* create a distinction between "boolean" and "flag". It's confusing enough that Quest uses two names for the same thing (I can guess why it evolved that way, but it's unfortunate). Adding a semantic distinction between two things that are actually the same is only going to confuse things even further.
So, "flag" equals "boolean attribute", exactly. No difference. The APIs use the word "flag" to be more non-techie friendly, but that's all it is, a difference in a term. There is no semantic difference, and (in my opinion) it's dangerous and confusing to assign one.
Ok, terminology out of the way... what are we really talking about here? Basically: do I pre-define my attributes (of any kind) or not? And the answer, as with all things, is "it depends".
I think for the purposes that most people use attributes for, it's better to define them up front. They are part of the "static type" of the object (to the extent that Quest has that). There is also a *big* gain, which is that using functions like GetBoolean, GetInt, etc. opens you up to untold grief with typos. If I get the name of an attribute wrong when I reference it directly, Quest will tell me right away. If I get the name wrong in "GetBoolean" without realizing it, then I'm probably going to lose a good chunk of my hair trying to figure out why things aren't working, and I'll really hate myself when I figure out why.
So I would say: only use “on-the-fly” attributes when it makes sense to from a design point of view.
(An aside: Performance? I'd be really interested to see the code where GetBoolean over direct access makes a noticeable difference in the performance of some code. (And please, don't contrive one: I know it's possible. I'm just saying, it's of such minor concern, that I wouldn't even go there.) Per Knuth: "Programmers waste enormous amounts of time thinking about, or worrying about, the speed of *noncritical* parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil." Or more to the point: only optimize after measuring. If you have a problem, then optimize. Otherwise, don't worry about it. Even something like "first time" vs setting and checking flags - we're probably talking about milliseconds difference here. Focus on what makes sense to you from a code style point of view, leave efficiency for those rare times where it actually makes a difference, and be at peace.

)
To go the other way, when does it make sense to not pre-define attributes, to define them “on-the-fly”? That is a design question, and as such, there are no hard-and-fast rules. Given the above problem with the Get* APIs regarding typos, I'd say you'd want to have good reason to not. But there are good reasons.
As an example: in my “response library”, I use a good number of on-the-fly attributes within the response objects. And the reason why is that I'm trying to make the code easier for people to use. There could potentially be so many response objects that I wanted to keep them as simple as possible, with a minimal footprint. All those attributes I'd be using were *internal bookkeeping* for the object, not a part of the fundamental definition of a response object. I wanted people to focus on defining the parts of the objects that needed it, not worry about adding in all the internal attributes the library needed. (That can be overcome with a type, to inject the attributes into the object, but I didn't even want to clutter up an object with that. I wanted the objects to be purely data.)
So I can think of several reasons to define attributes as needed:
1) They are not a fundamental part of the object but are used only in special case situations.
2) They correspond to “hidden” internal state which is best kept private. If I had said to those using my response objects, “You need to define these attributes in your objects” and then with a later rev, I found I needed more and said, “Now you have to go to each of your hundreds of objects and all these additional ones in, not for your use but for mine”, then people would have found out where I lived and hunted me down.
3) You are operating on a heterogeneous set of objects with no common base type. Quest is similar to JavaScript in that it supports “duck typing” (“if it walks like a duck and talks like a duck...”) where objects don't really have types but are measured by the attributes they possess. On-the-fly attributes allow you to "make ducks" dynamically. Let's say I want to create some code to operate across all Quest objects, regardless of what they are (room, player, apple, sword). It would be very inconvenient to a user of my code if I said, “For every object you pass to this function, you need to make sure these attributes are defined.” It's just too cumbersome, and it exposes users of my code to the internal workings. It's much more preferable to simply create the attributes on-the-fly as needed. It allows the code to inject its own personal state into the object without the user of the code needing to be aware of what is being done. It allows for encapsulation and data hiding, both good things in object-oriented design.
4) It could also be stylistic. I can imagine some wanting minimal objects, with attributes appearing only as needed. Why take up a slot for an attribute that's not needed? That really comes down to design and style. (But given the grief you can have with the Get* methods and typos, you'd have to really be dedicated to that approach.)
I hope I didn't waffle on too much. The short version is: you generally want to pre-define your attributes, of all kinds. It makes for a saner world in the common cases. And there is good company for that: there are languages like C, C++, Pascal, Ada, etc where you *must* define attributes in the static definition of an object.
But there are also really valid cases where you want to define attributes on-the-fly. As with many things, it all comes down to design.
(A minor note: GetBoolean returns false if the attribute doesn't exist, not null. I wish the other “Get” functions also returned reasonable defaults instead of null. It would make life so much easier.)