This type of curvature is much easier to create if you can do it using offset().
To create a 2D shape with rounded corners, you can do something like offset(inner_radius) offset (outer_radius - inner_radius) offset(-outer_radius) shape(). Note that any positive or negative features that go to zero width at any point during this process will be lost (you can often get around this by booleaning multiple shapes that already have their fillets applied). Also, you get a resolution difference in the convex/concave curves that depends on the order of the multiple offsets.
Otherwise, the solution involves finding the point where the two curves meet. Usually adding a square with a side equal to the circle's radius, with its corner at the circle's center, and rotated to that its edge is normal to the desired curve at the point where its curvature changes, but that math is usually more tedious than using the offset method.
The method using a bunch of offsets is the easiest, if that can do the job.
I wrote an "offset_stroke" that will take a series of points and draw a 2d
curve with specified width and with filleting to an arbitrary angle at both
ends. (It's in BOSL2.)
I'm very interested in this kind of problem, but I think the solutions often
need to be integrated with the method you used to make the curved shape.
That is, you need to have a representation of the curve and use that to
develop the fillet. I'm actually planning to write a function that will
blend two point lists with a curve between them. But of course, all of
these types of approaches require that you have a point list rather than