The overview is fairly light, but check out these slides from a presentation I did for New Game Conf last year:
https://docs.google.com/presentation/d/110MxOqut_y7KOW1pNwIdcccisIA3ooJwVR-xm-ecuc4/view
(see pertinent images below)
The gist of the technique is to combine the action list pattern (explained -- somewhat poorly -- in the slides) with behavioral state machines that act upon a component-based game entity.
It is in essence the same as creating a special composition system just for AI behavior, geared towards the kinds of inter-behavioral integration you need for simpler AI systems.
My favorite part of that particular game was how we could create entirely new types of enemies by simply selecting from a list of pre-written behaviors, put them into the action list for the game object (residing in a BrainComponent) in the order of desired priority, and everything just worked. With an action list that allows for Blocking/NonBlocking actions, this can do some really cool things despite how simple it all is to implement.
Even behaviors like "stun" where really just a StunBehaviorAction pushed onto the top of action list stack; if the stun behavior become activated (after observing that the game object's EarsComponent heard a stunning shockwave attack) then it set its internal state to Stunned, told the AnimationComponent to play the stun animation, and set its action state to Blocking, and its timer to a stun timeout pulled from the game object's EnemyParametersComponent. Since it was Blocking and at the top of the action list, none of the other BehaviorAction's in the action list would get their update method called, so they would essentially be switched off. When the timeout expired, the StunBehaviorAction set its state back to Idle and its action state to NonBlocking.
The other behaviors we implemented were almost all implemented with a single internal state machine. The only two that didn't have state machines, in fact, were the PatrolPathBehaviorAction (it would push a series of PathAction's onto the action list if it was idle, which in turn pushed MoveAction's) and the GuardHomeBehaviorAction (always at the bottom of the action list, and would always just push a PathAction back to the enemy's home location). Every other behavior was a state machine.
