You can't get the results of an `@future` method in the currently running transaction (the transaction from which the asynchronous call is made). The `@future` method will not even execute until the current transaction completes and commits successfully (i.e., no unhandled exceptions leading to a rollback). There is no workaround; this is an inherent feature of the design of the Salesforce platform.

What you can do is restructure how you are building your functionality to work *with* the way Salesforce handles asynchronous operations. I'm not familiar with DocuSign, but I'll assume for the sake of illustration that you have access to a `Docusign.voidEnvelopeSync()` method that does the same callout synchronously.

If that's the case, you can write your *own* future method that calls that synchronous method and then takes action based upon the result:

    @future(callout=true)
    public static void doCallout(... parameters ...) {
        // do things ...
        // then:
        if (appStatusesBelowDocSent.contains(currentAppStatus)) {     
            envelopeId = EsignUtil.getEnvelopeId(app.Id);   
            // We're already in an async, callout-permitted environment,
            // so perform the action synchronously here.                             
            Object result = Docusign.voidEnvelopeSync(envelopeId,'Application recalled or status is changed to a previous status'); 
    
            // Perform DML to update related object.
        }
    }