I’m not the smartest with transforming look vectors directly but I do know how to do it with CFrames!

local spreadAng = 20 -- later converted to radians
local r = math.rad(spreadAng)
local look = Vector3.new(0,0,1)
local origin = Vector3.new(0,10,0)
local cf = CFrame.new(origin,origin + look)
local randomUp = (math.random()*2 - 1)*r
local randomRight = (math.random()*2 - 1)*r
local transformedCF = cf * CFrame.Angles(randomUp,randomRight,0)

The transformedCF is going to have your new look vector via CF.LookVector. If this doesn’t work you may need to specify the order of the CF like so:

local transformedCF = cf * CFrame.Angles(randomUp,0,0) * CFrame.Angles(0,randomRight,0)

Fun fact: (math.random()*2 - 1) returns a number from -1 to 1, which is helpful in this case.

EDIT:
An alternative way to get it (and I think may be better in your case) may be to rotate the CFrame along the Z and then shift it up or down, like so:

local randomRot = math.random()*math.pi*2
local randomUp = (math.random()*2 - 1)*r
local transformedCF = cf * CFrame.Angles(0,0,randomRot) * CFrame.Angles(randomUp,0,0)

For fun, I came up with a solution that uses trigonometry and does transformations on the directional vectors. I don’t know how much this is functionally different from @Locard’s solution, but here it is anyway:

The Code

--Returns a random CFrame in the area
local function GenerateInArea(originCf, distance, areaRadius)
local angle = math.random() * math.pi * 2
local radius = math.random() * areaRadius
local lookOffset = originCf.LookVector * radius * math.cos(angle)
local rightOffset = originCf.RightVector * radius * math.sin(angle)
return originCf + originCf.LookVector * distance + lookOffset + rightOffset
end
local part = Instance.new("Part")
part.Name = "ResultPart"
part.Anchored = true
part.BrickColor = BrickColor.new("Really red")
part.Size = Vector3.new(2, 2, 2)
part.Parent = workspace
--This will place the part in a random place within a circular area of 10 studs that is
--20 studs away from the direction of the script.Parent (another part)
part.CFrame = GenerateInArea(script.Parent.CFrame, 20, 10)