diff --git a/briar-android-tests/src/test/java/org/briarproject/introduction/IntroductionIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/introduction/IntroductionIntegrationTest.java
index af71da19ecf105111c1f560dca79575e14b14f5e..364040e7ce3e864a10cb77add6598e0cb4bf1b0d 100644
--- a/briar-android-tests/src/test/java/org/briarproject/introduction/IntroductionIntegrationTest.java
+++ b/briar-android-tests/src/test/java/org/briarproject/introduction/IntroductionIntegrationTest.java
@@ -442,6 +442,54 @@ public class IntroductionIntegrationTest extends BriarTestCase {
 		}
 	}
 
+	@Test
+	public void testResponseAndAckInOneSession() throws Exception {
+		startLifecycles();
+
+		addDefaultIdentities();
+		addDefaultContacts();
+		addListeners(true, true);
+		addTransportProperties();
+
+		// make introduction
+		long time = clock.currentTimeMillis();
+		Contact introducee1 = contactManager0.getContact(contactId1);
+		Contact introducee2 = contactManager0.getContact(contactId2);
+		introductionManager0
+				.makeIntroduction(introducee1, introducee2, "Hi!", time);
+
+		// sync first request message
+		deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1");
+		eventWaiter.await(TIMEOUT, 1);
+		assertTrue(listener1.requestReceived);
+
+		// sync first response
+		deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0");
+		eventWaiter.await(TIMEOUT, 1);
+		assertTrue(listener0.response1Received);
+
+		// don't let 2 answer the request right away
+		// to have the response arrive first
+		listener2.answerRequests = false;
+
+		// sync second request message and first response
+		deliverMessage(sync0, contactId0, sync2, contactId2, 2, "0 to 2");
+		eventWaiter.await(TIMEOUT, 1);
+		assertTrue(listener2.requestReceived);
+
+		// answer request manually
+		introductionManager2
+				.acceptIntroduction(contactId0, listener2.sessionId, time);
+
+		// sync second response and ACK and make sure there is no abort
+		deliverMessage(sync2, contactId2, sync0, contactId0, 2, "2 to 0");
+		eventWaiter.await(TIMEOUT, 1);
+		assertTrue(listener0.response2Received);
+		assertFalse(listener0.aborted);
+
+		stopLifecycles();
+	}
+
 	@Test
 	public void testIntroductionToSameContact() throws Exception {
 		startLifecycles();
@@ -1169,6 +1217,8 @@ public class IntroductionIntegrationTest extends BriarTestCase {
 		private volatile boolean requestReceived = false;
 		private volatile boolean succeeded = false;
 		private volatile boolean aborted = false;
+		private volatile boolean answerRequests = true;
+		private volatile SessionId sessionId;
 
 		private final int introducee;
 		private final boolean accept;
@@ -1194,10 +1244,10 @@ public class IntroductionIntegrationTest extends BriarTestCase {
 				requestReceived = true;
 				IntroductionRequest ir = introEvent.getIntroductionRequest();
 				ContactId contactId = introEvent.getContactId();
-				SessionId sessionId = ir.getSessionId();
+				sessionId = ir.getSessionId();
 				long time = clock.currentTimeMillis();
 				try {
-					if (introducee == 1) {
+					if (introducee == 1 && answerRequests) {
 						if (accept) {
 							introductionManager1
 									.acceptIntroduction(contactId, sessionId,
@@ -1207,7 +1257,7 @@ public class IntroductionIntegrationTest extends BriarTestCase {
 									.declineIntroduction(contactId, sessionId,
 											time);
 						}
-					} else if (introducee == 2) {
+					} else if (introducee == 2 && answerRequests) {
 						if (accept) {
 							introductionManager2
 									.acceptIntroduction(contactId, sessionId,
diff --git a/briar-core/src/org/briarproject/introduction/IntroduceeManager.java b/briar-core/src/org/briarproject/introduction/IntroduceeManager.java
index a01734cb13a82b16ff42c0185c02c3efd91edd2d..4456a5671cb682d7af55bc2e50b597ea7a893525 100644
--- a/briar-core/src/org/briarproject/introduction/IntroduceeManager.java
+++ b/briar-core/src/org/briarproject/introduction/IntroduceeManager.java
@@ -32,6 +32,7 @@ import org.briarproject.api.sync.GroupId;
 import org.briarproject.api.sync.Message;
 import org.briarproject.api.sync.MessageId;
 import org.briarproject.api.system.Clock;
+import org.jetbrains.annotations.Nullable;
 
 import java.io.IOException;
 import java.security.GeneralSecurityException;
@@ -243,7 +244,7 @@ class IntroduceeManager {
 					result) throws DbException, FormatException {
 
 		// perform actions based on new local state
-		performTasks(txn, result.localState);
+		BdfDictionary followUpAction = performTasks(txn, result.localState);
 
 		// save new local state
 		MessageId storageId =
@@ -269,13 +270,21 @@ class IntroduceeManager {
 			db.deleteMessage(txn, messageId);
 			db.deleteMessageMetadata(txn, messageId);
 		}
+
+		// process follow up action at the end if available
+		if (followUpAction != null) {
+			IntroduceeEngine engine = new IntroduceeEngine();
+			processStateUpdate(txn, null,
+					engine.onLocalAction(result.localState, followUpAction));
+		}
 	}
 
-	private void performTasks(Transaction txn, BdfDictionary localState)
+	@Nullable
+	private BdfDictionary performTasks(Transaction txn, BdfDictionary localState)
 			throws FormatException, DbException {
 
 		if (!localState.containsKey(TASK) || localState.get(TASK) == NULL_VALUE)
-			return;
+			return null;
 
 		// remember task and remove it from localState
 		long task = localState.getLong(TASK);
@@ -285,7 +294,7 @@ class IntroduceeManager {
 			if (localState.getBoolean(EXISTS)) {
 				// we have this contact already, so do not perform actions
 				LOG.info("We have this contact already, do not add");
-				return;
+				return null;
 			}
 
 			// figure out who takes which role by comparing public keys
@@ -348,10 +357,9 @@ class IntroduceeManager {
 			BdfDictionary localAction = new BdfDictionary();
 			localAction.put(TYPE, TYPE_ACK);
 
-			// start engine and process its state update
-			IntroduceeEngine engine = new IntroduceeEngine();
-			processStateUpdate(txn, null,
-					engine.onLocalAction(localState, localAction));
+			// return follow up action to start engine
+			// and process its state update again
+			return localAction;
 		}
 
 		// we sent and received an ACK, so activate contact
@@ -394,6 +402,7 @@ class IntroduceeManager {
 				contactManager.removeContact(txn, contactId);
 			}
 		}
+		return null;
 	}
 
 	private SecretKey deriveSecretKey(byte[] publicKeyBytes,