I don’t see it on the API guide either. You can try copying the basic shell and replicate its behavior in your CAP.

For example, this basic Direction Until Tool Contact looks like this:
def calculate_point_to_move_towards(feature, direction, position_distance):
local posDir=[direction[0], direction[1], direction[2]]
if (norm(posDir) < 1e-6):
return get_target_waypoint()
end
local direction_vector_normalized=normalize(posDir)
local displacement_pose=p[direction_vector_normalized[0] * position_distance,direction_vector_normalized[1] * position_distance,direction_vector_normalized[2] * position_distance,0,0,0]
local wanted_displacement_in_base_frame=pose_sub(pose_trans(feature, displacement_pose), feature)
return pose_add(get_target_waypoint(), wanted_displacement_in_base_frame)
end
while (True):
$ 1 "Robot Program"
$ 2 "MoveL"
$ 3 "Direction: Base Z-"
global move_thread_flag_3=0
thread move_thread_3():
enter_critical
move_thread_flag_3 = 1
local towardsPos=calculate_point_to_move_towards(p[0.0,0.0,0.0,0.0,0.0,0.0], [0.0,0.0,-1.0], 1000.0)
movel(towardsPos, a=1.2, v=0.25)
move_thread_flag_3 = 2
exit_critical
end
move_thread_flag_3 = 0
move_thread_han_3 = run move_thread_3()
while (True):
local targetTcpDirection=get_target_tcp_speed()
local stepsToRetract=tool_contact(direction=targetTcpDirection)
if (stepsToRetract > 0):
kill move_thread_han_3
stopl(3.0)
local backTrackMovement=get_actual_joint_positions_history(stepsToRetract)
local contactPose=get_forward_kin(backTrackMovement)
local posDir=[targetTcpDirection[0],targetTcpDirection[1],targetTcpDirection[2]]
local retractTo=contactPose
if (norm(posDir) > 1e-6):
local normalizedPosDir=normalize(posDir)
local additionalRetraction=p[normalizedPosDir[0] * 0.0, normalizedPosDir[1] * 0.0, normalizedPosDir[2] * 0.0, 0, 0, 0]
retractTo = pose_sub(contactPose, additionalRetraction)
end
movel(retractTo, a=3.0, v=0.1)
$ 4 "Until (tool_contact_detection)"
$ 5 "Popup: This is the Action"
popup("This is the Action", "Message", False, False, blocking=True)
break
end
sync()
end
end
end
Which is uhhh a fair amount more complicated than I was expecting, to be honest.