Programatically Adding Fields to a Layout
While I am adding them from a plugin, I ran into a similar issue as you, and like you, I didn't like the "recreate the layout from scratch" method the linked answer used. I know this question is old, but it seems the most apt place to put my solution to this issue and contribute to more code samples.

After some experimenting, I got a solution that works (whether it's "the Craft way," I'm not totally sure, and I'm sure some of it could be cleaned up, but it's not like there's a lot of documentation on that front, as we've both found).

This code creates the fields, a field group, and a tab, then adds the tab and fields to the User Layout:

    // Create the field group
    $groupModel = new FieldGroupModel();
    $groupModel-&gt;name = 'CustomGroupName';
    craft()-&gt;fields-&gt;saveGroup($groupModel);

    // I haven't yet found a way to get the group ID without looping through all of the groups. saveGroup() returns a boolean and doesn't appear to update the id attribute of the original model instance.
    $groups = craft()-&gt;fields-&gt;getAllGroups();
    foreach($groups as $group) {
        if($group-&gt;name != 'CustomGroupName') {
            continue;
        }
        $groupModel = $group;
    }

    // Create the tab
    $tabModel = new FieldLayoutTabModel();
    // Get the desired layout (in this case, the User layout) and use the tab's setLayout to link the two
    $layout = craft()-&gt;fields-&gt;getLayoutByType(ElementType::User);
    $tabModel-&gt;setLayout($layout);
    $tabModel-&gt;name = 'CustomTabName';


    // Create the fields. I have a protected class member that contains the fields in a 'fieldName' =&gt; 'FieldName' format.
    foreach($this-&gt;fields as $field =&gt; $name) {
        $fieldModel = new FieldModel();
        $fieldModel-&gt;groupId = $groupModel-&gt;id;
        $fieldModel-&gt;name = Craft::t($name);
        $fieldModel-&gt;handle = $field;
        $fieldModel-&gt;translatable = false;
        $fieldModel-&gt;type = 'PlainText';

        craft()-&gt;fields-&gt;saveField($fieldModel);
    }

    // Get all of the group's fields. This could also be done by saving an array of the fields in the loop above, but this seems a bit cleaner to me, and since we already have the group object, saves us an object/variable declaration.
    $fields = $groupModel-&gt;getFields();

    // Set the tab's fields. This gives us a custom grouping in the layout editor.
    $tabModel-&gt;setFields($fields);

    // Get the existing tabs (and, by extension, fields), since we don't want to nuke the layout, just add to it. I couldn't find any sort of "addTab" type function, so this is how we have to do it.
    $layoutTabs = $layout-&gt;getTabs();

    // getTabs() returns an array, so simply add our new tab to the array.
    $layoutTabs[] = $tabModel;

    // Now, set the tabs back in the layout.
    $layout-&gt;setTabs($layoutTabs);


The reversal is exactly that--a reversal:

    $group = null;

    // Delete the fields
    foreach($this-&gt;fields as $field =&gt; $name) {
        $fieldModel = craft()-&gt;fields-&gt;getFieldByHandle($field);
        if($fieldModel) {
            // Grab the group from one of the fields. Presumably (in my case), they're all in the same group. This could be refined for a less ham-fisted approach. Unfortunately, it's either this, or doing the loop-through-all-groups method we did in the create section, that I've found.
            $group = $fieldModel-&gt;group;
            craft()-&gt;fields-&gt;deleteField($fieldModel);
        }
    }

    // Delete the field group
    if($group) {
        $groupModel = craft()-&gt;fields-&gt;getGroupById($group-&gt;id);
        // I made sure it was empty, since I don't want to delete the group if more fields were added.
        if($groupModel &amp;&amp; empty($groupModel-&gt;getFields())) {
            craft()-&gt;fields-&gt;deleteGroupById($groupModel-&gt;id);
        }
    }

    // Delete the layout tab
    // Get the layout...
    $layout = craft()-&gt;fields-&gt;getLayoutByType(ElementType::User);

    // Get the tabs...
    $tabs = $layout-&gt;tabs;

    // Find and delete the tab we want, in the same fashion, except now we're unsetting the array instead of setting it.
    foreach($tabs as $index =&gt; $tab) {
        if($tab-&gt;name != "CustomTabName") {
            continue;
        }
        unset($tabs[$index]);
    }
    $layout-&gt;setTabs($tabs);